Merge branch 'alpha/JAL-3362_Jalview_212_alpha' into alpha/merge_212_JalviewJS_2112
[jalview.git] / src / jalview / jbgui / GPreferences.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.jbgui;
22
23 import jalview.bin.Cache;
24 import jalview.fts.core.FTSDataColumnPreferences;
25 import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
26 import jalview.fts.service.pdb.PDBFTSRestClient;
27 import jalview.gui.Desktop;
28 import jalview.gui.JalviewBooleanRadioButtons;
29 import jalview.gui.JvOptionPane;
30 import jalview.gui.JvSwingUtils;
31 import jalview.gui.StructureViewer.ViewerType;
32 import jalview.io.BackupFilenameParts;
33 import jalview.io.BackupFiles;
34 import jalview.io.BackupFilesPresetEntry;
35 import jalview.io.IntKeyStringValueEntry;
36 import jalview.util.MessageManager;
37 import jalview.util.Platform;
38
39 import java.awt.BorderLayout;
40 import java.awt.Color;
41 import java.awt.Component;
42 import java.awt.Dimension;
43 import java.awt.FlowLayout;
44 import java.awt.Font;
45 import java.awt.GridBagConstraints;
46 import java.awt.GridBagLayout;
47 import java.awt.GridLayout;
48 import java.awt.Insets;
49 import java.awt.Rectangle;
50 import java.awt.event.ActionEvent;
51 import java.awt.event.ActionListener;
52 import java.awt.event.KeyEvent;
53 import java.awt.event.KeyListener;
54 import java.awt.event.MouseAdapter;
55 import java.awt.event.MouseEvent;
56 import java.util.Arrays;
57 import java.util.List;
58
59 import javax.swing.AbstractButton;
60 import javax.swing.AbstractCellEditor;
61 import javax.swing.BorderFactory;
62 import javax.swing.BoxLayout;
63 import javax.swing.ButtonGroup;
64 import javax.swing.DefaultListCellRenderer;
65 import javax.swing.JButton;
66 import javax.swing.JCheckBox;
67 import javax.swing.JComboBox;
68 import javax.swing.JComponent;
69 import javax.swing.JFileChooser;
70 import javax.swing.JLabel;
71 import javax.swing.JPanel;
72 import javax.swing.JRadioButton;
73 import javax.swing.JScrollPane;
74 import javax.swing.JSpinner;
75 import javax.swing.JTabbedPane;
76 import javax.swing.JTable;
77 import javax.swing.JTextArea;
78 import javax.swing.JTextField;
79 import javax.swing.ListSelectionModel;
80 import javax.swing.SpinnerModel;
81 import javax.swing.SpinnerNumberModel;
82 import javax.swing.SwingConstants;
83 import javax.swing.border.Border;
84 import javax.swing.border.EmptyBorder;
85 import javax.swing.border.EtchedBorder;
86 import javax.swing.border.TitledBorder;
87 import javax.swing.event.ChangeEvent;
88 import javax.swing.event.ChangeListener;
89 import javax.swing.table.TableCellEditor;
90 import javax.swing.table.TableCellRenderer;
91
92 import net.miginfocom.swing.MigLayout;
93
94 /**
95  * Base class for the Preferences panel.
96  * 
97  * @author $author$
98  * @version $Revision$
99  */
100 public class GPreferences extends JPanel
101 {
102   private static final Font LABEL_FONT = JvSwingUtils.getLabelFont();
103
104   private static final Font LABEL_FONT_ITALIC = JvSwingUtils
105           .getLabelFont(false, true);
106
107   private static final Font LABEL_FONT_BOLD = JvSwingUtils
108           .getLabelFont(true, false);
109
110   /*
111    * Visual tab components
112    */
113   protected JCheckBox fullScreen = new JCheckBox();
114
115   protected JCheckBox openoverv = new JCheckBox();
116
117   protected JCheckBox seqLimit = new JCheckBox();
118
119   protected JCheckBox rightAlign = new JCheckBox();
120
121   protected JComboBox<String> fontSizeCB = new JComboBox<>();
122
123   protected JComboBox<String> fontStyleCB = new JComboBox<>();
124
125   protected JComboBox<String> fontNameCB = new JComboBox<>();
126
127   protected JCheckBox showOccupancy = new JCheckBox();
128
129   protected JCheckBox showUnconserved = new JCheckBox();
130
131   protected JCheckBox idItalics = new JCheckBox();
132
133   protected JCheckBox smoothFont = new JCheckBox();
134
135   protected JCheckBox scaleProteinToCdna = new JCheckBox();
136
137   protected JComboBox<String> gapSymbolCB = new JComboBox<>();
138
139   protected JCheckBox wrap = new JCheckBox();
140
141   protected JComboBox<String> sortby = new JComboBox<>();
142
143   protected JComboBox<String> sortAnnBy = new JComboBox<>();
144
145   protected JComboBox<String> sortAutocalc = new JComboBox<>();
146
147   protected JCheckBox startupCheckbox = new JCheckBox();
148
149   protected JTextField startupFileTextfield = new JTextField();
150
151   // below are in the 'second column'
152   protected JCheckBox annotations = new JCheckBox();
153
154   protected JCheckBox quality = new JCheckBox();
155
156   protected JCheckBox conservation = new JCheckBox();
157
158   protected JCheckBox identity = new JCheckBox();
159
160   protected JCheckBox showGroupConsensus = new JCheckBox();
161
162   protected JCheckBox showGroupConservation = new JCheckBox();
163
164   protected JCheckBox showConsensHistogram = new JCheckBox();
165
166   protected JCheckBox showConsensLogo = new JCheckBox();
167
168   protected JCheckBox showInformationHistogram = new JCheckBox();
169
170   protected JCheckBox showHMMLogo = new JCheckBox();
171
172   protected JCheckBox showDbRefTooltip = new JCheckBox();
173
174   protected JCheckBox showNpTooltip = new JCheckBox();
175
176
177   /*
178    * Structure tab and components
179    */
180   protected JPanel structureTab;
181
182   protected JCheckBox structFromPdb = new JCheckBox();
183
184   protected JCheckBox useRnaView = new JCheckBox();
185
186   protected JCheckBox addSecondaryStructure = new JCheckBox();
187
188   protected JCheckBox addTempFactor = new JCheckBox();
189
190   protected JComboBox<String> structViewer = new JComboBox<>();
191
192   protected JTextField chimeraPath = new JTextField();
193
194   protected ButtonGroup mappingMethod = new ButtonGroup();
195
196   protected JRadioButton siftsMapping = new JRadioButton();
197
198   protected JRadioButton nwMapping = new JRadioButton();
199
200   /*
201    * Colours tab components
202    */
203   protected JPanel minColour = new JPanel();
204
205   protected JPanel maxColour = new JPanel();
206
207   protected JComboBox<String> protColour = new JComboBox<>();
208
209   protected JComboBox<String> nucColour = new JComboBox<>();
210
211   /*
212    * Overview tab components
213    */
214   protected JPanel gapColour = new JPanel();
215
216   protected JPanel hiddenColour = new JPanel();
217
218   protected JCheckBox useLegacyGap;
219
220   protected JCheckBox showHiddenAtStart;
221
222   protected JLabel gapLabel;
223
224   /*
225    * Connections tab components
226    */
227   protected JTable linkUrlTable = new JTable();
228
229   protected JButton editLink = new JButton();
230
231   protected JButton deleteLink = new JButton();
232
233   protected JTextField filterTB = new JTextField();
234
235   protected JButton doReset = new JButton();
236
237   protected JButton userOnly = new JButton();
238
239   protected JLabel portLabel = new JLabel();
240
241   protected JLabel serverLabel = new JLabel();
242
243   protected JTextField proxyServerTB = new JTextField();
244
245   protected JTextField proxyPortTB = new JTextField();
246
247   protected JTextField defaultBrowser = new JTextField();
248
249   protected JCheckBox useProxy = new JCheckBox();
250
251   protected JCheckBox usagestats = new JCheckBox();
252
253   protected JCheckBox questionnaire = new JCheckBox();
254
255   protected JCheckBox versioncheck = new JCheckBox();
256
257   /*
258    * Output tab components
259    */
260   protected JComboBox<Object> epsRendering = new JComboBox<>();
261
262   protected JComboBox<Object> htmlRendering = new JComboBox<>();
263
264   protected JComboBox<Object> svgRendering = new JComboBox<>();
265
266   protected JLabel userIdWidthlabel = new JLabel();
267
268   protected JCheckBox autoIdWidth = new JCheckBox();
269
270   protected JTextField userIdWidth = new JTextField();
271
272   protected JCheckBox blcjv = new JCheckBox();
273
274   protected JCheckBox pileupjv = new JCheckBox();
275
276   protected JCheckBox clustaljv = new JCheckBox();
277
278   protected JCheckBox msfjv = new JCheckBox();
279
280   protected JCheckBox fastajv = new JCheckBox();
281
282   protected JCheckBox pfamjv = new JCheckBox();
283
284   protected JCheckBox pirjv = new JCheckBox();
285
286   protected JCheckBox modellerOutput = new JCheckBox();
287
288   protected JCheckBox embbedBioJSON = new JCheckBox();
289
290   /*
291    * Editing tab components
292    */
293   protected JCheckBox autoCalculateConsCheck = new JCheckBox();
294
295   protected JCheckBox padGaps = new JCheckBox();
296
297   protected JCheckBox sortByTree = new JCheckBox();
298
299   /*
300    * hmmer tab and components
301    */
302   protected JPanel hmmerTab;
303
304   protected JCheckBox hmmrTrimTermini;
305
306   protected AbstractButton hmmerBackgroundUniprot;
307
308   protected AbstractButton hmmerBackgroundAlignment;
309
310   protected JTextField hmmerSequenceCount;
311
312   protected JTextField hmmerPath;
313
314   protected JTextField cygwinPath;
315
316   /*
317    * Web Services tab
318    */
319   protected JPanel wsTab = new JPanel();
320
321   /*
322    * Backups tab components
323    * a lot of these are member variables instead of local variables only so that they
324    * can be enabled/disabled easily in one go
325    */
326
327   protected JCheckBox enableBackupFiles = new JCheckBox();
328
329   protected JPanel presetsPanel = new JPanel();
330
331   protected JLabel presetsComboLabel = new JLabel();
332
333   protected JCheckBox customiseCheckbox = new JCheckBox();
334
335   protected JButton revertButton = new JButton();
336
337   protected JComboBox<Object> backupfilesPresetsCombo = new JComboBox<>();
338
339   private int backupfilesPresetsComboLastSelected = 0;
340
341   protected JPanel suffixPanel = new JPanel();
342
343   protected JPanel keepfilesPanel = new JPanel();
344
345   protected JPanel exampleFilesPanel = new JPanel();
346
347   protected JTextField suffixTemplate = new JTextField(null, 8);
348
349   protected JLabel suffixTemplateLabel = new JLabel();
350
351   protected JLabel suffixDigitsLabel = new JLabel();
352
353   protected JSpinner suffixDigitsSpinner = new JSpinner();
354
355   protected JalviewBooleanRadioButtons suffixReverse = new JalviewBooleanRadioButtons();
356
357   protected JalviewBooleanRadioButtons backupfilesKeepAll = new JalviewBooleanRadioButtons();
358
359   public JSpinner backupfilesRollMaxSpinner = new JSpinner();
360
361   protected JLabel oldBackupFilesLabel = new JLabel();
362
363   protected JalviewBooleanRadioButtons backupfilesConfirmDelete = new JalviewBooleanRadioButtons();
364
365   protected JTextArea backupfilesExampleLabel = new JTextArea();
366
367   /**
368    * Creates a new GPreferences object.
369    */
370   public GPreferences()
371   {
372     try
373     {
374       jbInit();
375     } catch (Exception ex)
376     {
377       ex.printStackTrace();
378     }
379   }
380
381   /**
382    * Construct the panel and its tabbed sub-panels.
383    * 
384    * @throws Exception
385    */
386   private void jbInit() throws Exception
387   {
388     final JTabbedPane tabbedPane = new JTabbedPane();
389     this.setLayout(new BorderLayout());
390     JPanel okCancelPanel = initOkCancelPanel();
391     this.add(tabbedPane, BorderLayout.CENTER);
392     this.add(okCancelPanel, BorderLayout.SOUTH);
393
394     tabbedPane.add(initVisualTab(),
395             MessageManager.getString("label.visual"));
396
397     tabbedPane.add(initColoursTab(),
398             MessageManager.getString("label.colours"));
399
400     tabbedPane.add(initOverviewTab(),
401             MessageManager.getString("label.overview"));
402
403     tabbedPane.add(initStructureTab(),
404             MessageManager.getString("label.structure"));
405
406     tabbedPane.add(initConnectionsTab(),
407             MessageManager.getString("label.connections"));
408
409         if (!Platform.isJS()) 
410         {
411           tabbedPane.add(initBackupsTab(), 
412                         MessageManager.getString("label.backups"));
413         }
414
415     tabbedPane.add(initLinksTab(),
416             MessageManager.getString("label.urllinks"));
417
418     tabbedPane.add(initOutputTab(),
419             MessageManager.getString("label.output"));
420
421     tabbedPane.add(initEditingTab(),
422             MessageManager.getString("label.editing"));
423
424     tabbedPane.add(initHMMERTab(), MessageManager.getString("label.hmmer"));
425
426     /*
427      * See WsPreferences for the real work of configuring this tab.
428      */
429     if (!Platform.isJS())
430     {
431       wsTab.setLayout(new BorderLayout());
432       tabbedPane.add(wsTab, MessageManager.getString("label.web_services"));
433     }
434
435     /*
436      * Handler to validate a tab before leaving it - currently only for
437      * Structure
438      */
439     tabbedPane.addChangeListener(new ChangeListener()
440     {
441       private Component lastTab;
442
443       @Override
444       public void stateChanged(ChangeEvent e)
445       {
446         if (lastTab == structureTab
447                 && tabbedPane.getSelectedComponent() != structureTab)
448         {
449           if (!validateStructure())
450           {
451             tabbedPane.setSelectedComponent(structureTab);
452             return;
453           }
454         }
455         lastTab = tabbedPane.getSelectedComponent();
456       }
457
458     });
459   }
460
461   /**
462    * Initialises the Editing tabbed panel.
463    * 
464    * @return
465    */
466   private JPanel initEditingTab()
467   {
468     JPanel editingTab = new JPanel();
469     editingTab.setLayout(null);
470     autoCalculateConsCheck.setFont(LABEL_FONT);
471     autoCalculateConsCheck.setText(
472             MessageManager.getString("label.autocalculate_consensus"));
473     autoCalculateConsCheck.setBounds(new Rectangle(21, 52, 209, 23));
474     padGaps.setFont(LABEL_FONT);
475     padGaps.setText(
476             MessageManager.getString("label.pad_gaps_when_editing"));
477     padGaps.setBounds(new Rectangle(22, 94, 168, 23));
478     sortByTree.setFont(LABEL_FONT);
479     sortByTree
480             .setText(MessageManager.getString("label.sort_with_new_tree"));
481     sortByTree.setToolTipText(MessageManager.getString(
482             "label.any_trees_calculated_or_loaded_alignment_automatically_sort"));
483     sortByTree.setBounds(new Rectangle(22, 136, 168, 23));
484     editingTab.add(autoCalculateConsCheck);
485     editingTab.add(padGaps);
486     editingTab.add(sortByTree);
487     return editingTab;
488   }
489
490   /**
491    * Initialises the hmmer tabbed panel
492    * 
493    * @return
494    */
495   private JPanel initHMMERTab()
496   {
497     hmmerTab = new JPanel();
498     hmmerTab.setLayout(new BoxLayout(hmmerTab, BoxLayout.Y_AXIS));
499     hmmerTab.setLayout(new MigLayout("flowy"));
500
501     /*
502      * path to hmmer binaries folder
503      */
504     JPanel installationPanel = new JPanel(new MigLayout("flowy"));
505     // new FlowLayout(FlowLayout.LEFT));
506     JvSwingUtils.createTitledBorder(installationPanel,
507             MessageManager.getString("label.installation"), true);
508     hmmerTab.add(installationPanel);
509     JLabel hmmerLocation = new JLabel(
510             MessageManager.getString("label.hmmer_location"));
511     hmmerLocation.setFont(LABEL_FONT);
512     final int pathFieldLength = 40;
513     hmmerPath = new JTextField(pathFieldLength);
514     hmmerPath.addMouseListener(new MouseAdapter()
515     {
516       @Override
517       public void mouseClicked(MouseEvent e)
518       {
519         if (e.getClickCount() == 2)
520         {
521           String chosen = openFileChooser(true);
522           if (chosen != null)
523           {
524             hmmerPath.setText(chosen);
525             validateHmmerPath();
526           }
527         }
528       }
529     });
530     installationPanel.add(hmmerLocation);
531     installationPanel.add(hmmerPath);
532
533     /*
534      * path to Cygwin binaries folder (for Windows)
535      */
536     if (Platform.isWindowsAndNotJS())
537     {
538       JLabel cygwinLocation = new JLabel(
539               MessageManager.getString("label.cygwin_location"));
540       cygwinLocation.setFont(LABEL_FONT);
541       cygwinPath = new JTextField(pathFieldLength);
542       cygwinPath.addMouseListener(new MouseAdapter()
543       {
544         @Override
545         public void mouseClicked(MouseEvent e)
546         {
547           if (e.getClickCount() == 2)
548           {
549             String chosen = openFileChooser(true);
550             if (chosen != null)
551             {
552               cygwinPath.setText(chosen);
553               validateCygwinPath();
554             }
555           }
556         }
557       });
558       installationPanel.add(cygwinLocation);
559       installationPanel.add(cygwinPath);
560     }
561
562     /*
563      * preferences for hmmalign
564      */
565     JPanel alignOptionsPanel = new JPanel(new MigLayout());
566     // new FlowLayout(FlowLayout.LEFT));
567     JvSwingUtils.createTitledBorder(alignOptionsPanel,
568             MessageManager.getString("label.hmmalign_options"), true);
569     hmmerTab.add(alignOptionsPanel);
570     hmmrTrimTermini = new JCheckBox();
571     hmmrTrimTermini.setFont(LABEL_FONT);
572     hmmrTrimTermini.setText(MessageManager.getString("label.trim_termini"));
573     alignOptionsPanel.add(hmmrTrimTermini);
574
575     /*
576      * preferences for hmmsearch
577      */
578     JPanel searchOptions = new JPanel(new MigLayout());
579     // FlowLayout(FlowLayout.LEFT));
580     JvSwingUtils.createTitledBorder(searchOptions,
581             MessageManager.getString("label.hmmsearch_options"), true);
582     hmmerTab.add(searchOptions);
583     JLabel sequencesToKeep = new JLabel(
584             MessageManager.getString("label.no_of_sequences"));
585     sequencesToKeep.setFont(LABEL_FONT);
586     searchOptions.add(sequencesToKeep);
587     hmmerSequenceCount = new JTextField(5);
588     searchOptions.add(hmmerSequenceCount);
589
590     /*
591      * preferences for Information Content annotation
592      */
593     // JPanel dummy = new JPanel(new FlowLayout(FlowLayout.LEFT));
594     JPanel annotationOptions = new JPanel(new MigLayout("left"));
595     JvSwingUtils.createTitledBorder(annotationOptions,
596             MessageManager.getString("label.information_annotation"), true);
597     // dummy.add(annotationOptions);
598     hmmerTab.add(annotationOptions);
599     ButtonGroup backgroundOptions = new ButtonGroup();
600     hmmerBackgroundUniprot = new JRadioButton(
601             MessageManager.getString("label.freq_uniprot"));
602     hmmerBackgroundUniprot.setFont(LABEL_FONT);
603     hmmerBackgroundAlignment = new JRadioButton(
604             MessageManager.getString("label.freq_alignment"));
605     hmmerBackgroundAlignment.setFont(LABEL_FONT);
606     backgroundOptions.add(hmmerBackgroundUniprot);
607     backgroundOptions.add(hmmerBackgroundAlignment);
608     backgroundOptions.setSelected(hmmerBackgroundUniprot.getModel(), true);
609     // disable buttons for now as annotation only uses Uniprot background
610     hmmerBackgroundAlignment.setEnabled(false);
611     hmmerBackgroundUniprot.setEnabled(false);
612     annotationOptions.add(hmmerBackgroundUniprot, "wrap");
613     annotationOptions.add(hmmerBackgroundAlignment);
614
615     return hmmerTab;
616   }
617
618   /**
619    * Initialises the Output tabbed panel.
620    * 
621    * @return
622    */
623   private JPanel initOutputTab()
624   {
625     JPanel outputTab = new JPanel();
626     outputTab.setLayout(null);
627
628     JLabel epsLabel = new JLabel(
629             MessageManager.formatMessage("label.rendering_style", "EPS"));
630     epsLabel.setFont(LABEL_FONT);
631     epsLabel.setHorizontalAlignment(SwingConstants.RIGHT);
632     epsLabel.setBounds(new Rectangle(9, 31, 160, 24));
633     epsRendering.setFont(LABEL_FONT);
634     epsRendering.setBounds(new Rectangle(174, 34, 187, 21));
635     JLabel htmlLabel = new JLabel(
636             MessageManager.formatMessage("label.rendering_style", "HTML"));
637     htmlLabel.setFont(LABEL_FONT);
638     htmlLabel.setHorizontalAlignment(SwingConstants.RIGHT);
639     htmlLabel.setBounds(new Rectangle(9, 55, 160, 24));
640     htmlRendering.setFont(LABEL_FONT);
641     htmlRendering.setBounds(new Rectangle(174, 58, 187, 21));
642     JLabel svgLabel = new JLabel(
643             MessageManager.formatMessage("label.rendering_style", "SVG"));
644     svgLabel.setFont(LABEL_FONT);
645     svgLabel.setHorizontalAlignment(SwingConstants.RIGHT);
646     svgLabel.setBounds(new Rectangle(9, 79, 160, 24));
647     svgRendering.setFont(LABEL_FONT);
648     svgRendering.setBounds(new Rectangle(174, 82, 187, 21));
649
650     JLabel jLabel1 = new JLabel();
651     jLabel1.setFont(LABEL_FONT);
652     jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
653     jLabel1.setText(MessageManager.getString("label.append_start_end"));
654     jLabel1.setFont(LABEL_FONT);
655
656     fastajv.setFont(LABEL_FONT);
657     fastajv.setHorizontalAlignment(SwingConstants.LEFT);
658     clustaljv.setText(MessageManager.getString("label.clustal") + "     ");
659     blcjv.setText(MessageManager.getString("label.blc") + "     ");
660     fastajv.setText(MessageManager.getString("label.fasta") + "     ");
661     msfjv.setText(MessageManager.getString("label.msf") + "     ");
662     pfamjv.setText(MessageManager.getString("label.pfam") + "     ");
663     pileupjv.setText(MessageManager.getString("label.pileup") + "     ");
664     msfjv.setFont(LABEL_FONT);
665     msfjv.setHorizontalAlignment(SwingConstants.LEFT);
666     pirjv.setText(MessageManager.getString("label.pir") + "     ");
667     JPanel jPanel11 = new JPanel();
668     jPanel11.setFont(LABEL_FONT);
669     TitledBorder titledBorder2 = new TitledBorder(
670             MessageManager.getString("label.file_output"));
671     jPanel11.setBorder(titledBorder2);
672     jPanel11.setBounds(new Rectangle(30, 120, 196, 182));
673     GridLayout gridLayout3 = new GridLayout();
674     jPanel11.setLayout(gridLayout3);
675     gridLayout3.setRows(8);
676     blcjv.setFont(LABEL_FONT);
677     blcjv.setHorizontalAlignment(SwingConstants.LEFT);
678     clustaljv.setFont(LABEL_FONT);
679     clustaljv.setHorizontalAlignment(SwingConstants.LEFT);
680     pfamjv.setFont(LABEL_FONT);
681     pfamjv.setHorizontalAlignment(SwingConstants.LEFT);
682     pileupjv.setFont(LABEL_FONT);
683     pileupjv.setHorizontalAlignment(SwingConstants.LEFT);
684     pirjv.setFont(LABEL_FONT);
685     pirjv.setHorizontalAlignment(SwingConstants.LEFT);
686     autoIdWidth.setFont(LABEL_FONT);
687     autoIdWidth.setText(
688             MessageManager.getString("label.automatically_set_id_width"));
689     autoIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
690             .getString("label.adjusts_width_generated_eps_png")));
691     autoIdWidth.setBounds(new Rectangle(228, 144, 320, 23));
692     autoIdWidth.addActionListener(new ActionListener()
693     {
694
695       @Override
696       public void actionPerformed(ActionEvent e)
697       {
698         autoIdWidth_actionPerformed();
699       }
700     });
701     userIdWidthlabel.setFont(LABEL_FONT);
702     userIdWidthlabel.setText(
703             MessageManager.getString("label.figure_id_column_width"));
704     userIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
705             .getString("label.manually_specify_width_left_column")));
706     userIdWidthlabel.setToolTipText(
707             JvSwingUtils.wrapTooltip(true, MessageManager.getString(
708                     "label.manually_specify_width_left_column")));
709     userIdWidthlabel.setBounds(new Rectangle(236, 168, 320, 23));
710     userIdWidth.setFont(JvSwingUtils.getTextAreaFont());
711     userIdWidth.setText("");
712     userIdWidth.setBounds(new Rectangle(232, 192, 84, 23));
713     userIdWidth.addActionListener(new ActionListener()
714     {
715
716       @Override
717       public void actionPerformed(ActionEvent e)
718       {
719         userIdWidth_actionPerformed();
720       }
721     });
722     modellerOutput.setFont(LABEL_FONT);
723     modellerOutput
724             .setText(MessageManager.getString("label.use_modeller_output"));
725     modellerOutput.setBounds(new Rectangle(228, 274, 320, 23));
726     embbedBioJSON.setFont(LABEL_FONT);
727     embbedBioJSON.setText(MessageManager.getString("label.embbed_biojson"));
728     embbedBioJSON.setBounds(new Rectangle(228, 248, 250, 23));
729
730     jPanel11.add(jLabel1);
731     jPanel11.add(blcjv);
732     jPanel11.add(clustaljv);
733     jPanel11.add(fastajv);
734     jPanel11.add(msfjv);
735     jPanel11.add(pfamjv);
736     jPanel11.add(pileupjv);
737     jPanel11.add(pirjv);
738     outputTab.add(autoIdWidth);
739     outputTab.add(userIdWidth);
740     outputTab.add(userIdWidthlabel);
741     outputTab.add(modellerOutput);
742     if (!Platform.isJS())
743     {
744       /*
745        * JalviewJS doesn't support Lineart option or SVG output
746        */
747       outputTab.add(embbedBioJSON);
748       outputTab.add(epsLabel);
749       outputTab.add(epsRendering);
750       outputTab.add(htmlLabel);
751       outputTab.add(htmlRendering);
752       outputTab.add(svgLabel);
753       outputTab.add(svgRendering);
754     }
755     outputTab.add(jPanel11);
756     return outputTab;
757   }
758
759   /**
760    * Initialises the Connections tabbed panel.
761    * 
762    * @return
763    */
764   private JPanel initConnectionsTab()
765   {
766     JPanel connectTab = new JPanel();
767     connectTab.setLayout(new GridBagLayout());
768
769     // Label for browser text box
770     JLabel browserLabel = new JLabel();
771     browserLabel.setFont(LABEL_FONT);
772     browserLabel.setHorizontalAlignment(SwingConstants.TRAILING);
773     browserLabel.setText(
774             MessageManager.getString("label.default_browser_unix"));
775     defaultBrowser.setFont(LABEL_FONT);
776     defaultBrowser.setText("");
777     final String tooltip = JvSwingUtils.wrapTooltip(true,
778             MessageManager.getString("label.double_click_to_browse"));
779     defaultBrowser.setToolTipText(tooltip);
780     defaultBrowser.addMouseListener(new MouseAdapter()
781     {
782       @Override
783       public void mouseClicked(MouseEvent e)
784       {
785         if (e.getClickCount() > 1)
786         {
787           defaultBrowser_mouseClicked(e);
788         }
789       }
790     });
791
792     JPanel proxyPanel = initConnTabProxyPanel();
793     initConnTabCheckboxes();
794
795     // Add default Browser text box
796     connectTab.add(browserLabel,
797             new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
798                     GridBagConstraints.WEST, GridBagConstraints.NONE,
799                     new Insets(10, 0, 5, 5), 5, 1));
800     defaultBrowser.setFont(LABEL_FONT);
801     defaultBrowser.setText("");
802
803     connectTab.add(defaultBrowser, new GridBagConstraints(1, 0, 1, 1, 1.0,
804             0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
805             new Insets(10, 0, 5, 10), 30, 1));
806
807     // Add proxy server panel
808     connectTab.add(proxyPanel, new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0,
809             GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
810             new Insets(10, 0, 5, 12), 4, 10));
811
812     // Add usage stats, version check and questionnaire checkboxes
813     connectTab.add(usagestats,
814             new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
815                     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
816                     new Insets(0, 2, 5, 5), 70, 1));
817     connectTab.add(questionnaire,
818             new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0,
819                     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
820                     new Insets(0, 2, 5, 10), 70, 1));
821     connectTab.add(versioncheck,
822             new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0,
823                     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
824                     new Insets(0, 2, 5, 5), 70, 1));
825
826     versioncheck.setVisible(false);
827
828     // Add padding so the panel doesn't look ridiculous
829     JPanel spacePanel = new JPanel();
830     connectTab.add(spacePanel,
831             new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
832                     GridBagConstraints.WEST, GridBagConstraints.BOTH,
833                     new Insets(0, 0, 0, 5), 70, 1));
834
835     return connectTab;
836   }
837
838   /**
839    * Initialises the Links tabbed panel.
840    * 
841    * @return
842    */
843   private JPanel initLinksTab()
844   {
845     JPanel linkTab = new JPanel();
846     linkTab.setLayout(new GridBagLayout());
847
848     // Set up table for Url links
849     linkUrlTable.getTableHeader().setReorderingAllowed(false);
850     linkUrlTable.setFillsViewportHeight(true);
851     linkUrlTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
852     linkUrlTable.setAutoCreateRowSorter(true);
853     linkUrlTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
854
855     // adjust row height so radio buttons actually fit
856     // don't do this in the renderer, it causes the awt thread to activate
857     // constantly
858     JRadioButton temp = new JRadioButton();
859     linkUrlTable.setRowHeight(temp.getMinimumSize().height);
860
861     // Table in scrollpane so that the table is given a scrollbar
862     JScrollPane linkScrollPane = new JScrollPane(linkUrlTable);
863     linkScrollPane.setBorder(null);
864
865     // Panel for links functionality
866     JPanel linkPanel = new JPanel(new GridBagLayout());
867     linkPanel.setBorder(new TitledBorder(
868             MessageManager.getString("label.url_linkfrom_sequence_id")));
869
870     // Put the Url links panel together
871
872     // Buttons go at top right, resizing only resizes the blank space vertically
873     JPanel buttonPanel = initLinkTabUrlButtons();
874     GridBagConstraints linkConstraints1 = new GridBagConstraints();
875     linkConstraints1.insets = new Insets(0, 0, 5, 0);
876     linkConstraints1.gridx = 0;
877     linkConstraints1.gridy = 0;
878     linkConstraints1.weightx = 1.0;
879     linkConstraints1.fill = GridBagConstraints.HORIZONTAL;
880     linkTab.add(buttonPanel, linkConstraints1);
881
882     // Links table goes at top left, resizing resizes the table
883     GridBagConstraints linkConstraints2 = new GridBagConstraints();
884     linkConstraints2.insets = new Insets(0, 0, 5, 5);
885     linkConstraints2.gridx = 0;
886     linkConstraints2.gridy = 1;
887     linkConstraints2.weightx = 1.0;
888     linkConstraints2.weighty = 1.0;
889     linkConstraints2.fill = GridBagConstraints.BOTH;
890     linkTab.add(linkScrollPane, linkConstraints2);
891
892     // Filter box and buttons goes at bottom left, resizing resizes the text box
893     JPanel filterPanel = initLinkTabFilterPanel();
894     GridBagConstraints linkConstraints3 = new GridBagConstraints();
895     linkConstraints3.insets = new Insets(0, 0, 0, 5);
896     linkConstraints3.gridx = 0;
897     linkConstraints3.gridy = 2;
898     linkConstraints3.weightx = 1.0;
899     linkConstraints3.fill = GridBagConstraints.HORIZONTAL;
900     linkTab.add(filterPanel, linkConstraints3);
901
902     return linkTab;
903   }
904
905   private JPanel initLinkTabFilterPanel()
906   {
907     // Filter textbox and reset button
908     JLabel filterLabel = new JLabel(
909             MessageManager.getString("label.filter"));
910     filterLabel.setFont(LABEL_FONT);
911     filterLabel.setHorizontalAlignment(SwingConstants.RIGHT);
912     filterLabel.setHorizontalTextPosition(SwingConstants.LEADING);
913
914     filterTB.setFont(LABEL_FONT);
915     filterTB.setText("");
916
917     doReset.setText(MessageManager.getString("action.showall"));
918     userOnly.setText(MessageManager.getString("action.customfilter"));
919
920     // Panel for filter functionality
921     JPanel filterPanel = new JPanel(new GridBagLayout());
922     filterPanel.setBorder(new TitledBorder("Filter"));
923     GridBagConstraints gbc = new GridBagConstraints();
924     gbc.gridx = 0;
925     gbc.gridy = 0;
926     gbc.fill = GridBagConstraints.NONE;
927     gbc.anchor = GridBagConstraints.WEST;
928
929     filterPanel.add(filterLabel, gbc);
930
931     GridBagConstraints gbc1 = new GridBagConstraints();
932     gbc1.gridx = 1;
933     gbc1.gridwidth = 2;
934     gbc1.fill = GridBagConstraints.HORIZONTAL;
935     gbc1.anchor = GridBagConstraints.WEST;
936     gbc1.weightx = 1.0;
937     filterPanel.add(filterTB, gbc1);
938
939     GridBagConstraints gbc2 = new GridBagConstraints();
940     gbc2.gridx = 3;
941     gbc2.fill = GridBagConstraints.NONE;
942     gbc2.anchor = GridBagConstraints.WEST;
943     filterPanel.add(doReset, gbc2);
944
945     GridBagConstraints gbc3 = new GridBagConstraints();
946     gbc3.gridx = 4;
947     gbc3.fill = GridBagConstraints.NONE;
948     gbc3.anchor = GridBagConstraints.WEST;
949     filterPanel.add(userOnly, gbc3);
950
951     return filterPanel;
952   }
953
954   private JPanel initLinkTabUrlButtons()
955   {
956     // Buttons for new / edit / delete Url links
957     JButton newLink = new JButton();
958     newLink.setText(MessageManager.getString("action.new"));
959
960     editLink.setText(MessageManager.getString("action.edit"));
961
962     deleteLink.setText(MessageManager.getString("action.delete"));
963
964     // no current selection, so initially disable delete/edit buttons
965     editLink.setEnabled(false);
966     deleteLink.setEnabled(false);
967
968     newLink.addActionListener(new java.awt.event.ActionListener()
969     {
970       @Override
971       public void actionPerformed(ActionEvent e)
972       {
973         newLink_actionPerformed(e);
974       }
975     });
976
977     editLink.setText(MessageManager.getString("action.edit"));
978     editLink.addActionListener(new java.awt.event.ActionListener()
979     {
980       @Override
981       public void actionPerformed(ActionEvent e)
982       {
983         editLink_actionPerformed(e);
984       }
985     });
986
987     deleteLink.setText(MessageManager.getString("action.delete"));
988     deleteLink.addActionListener(new java.awt.event.ActionListener()
989     {
990       @Override
991       public void actionPerformed(ActionEvent e)
992       {
993         deleteLink_actionPerformed(e);
994       }
995     });
996
997     JPanel buttonPanel = new JPanel(new GridBagLayout());
998     buttonPanel.setBorder(new TitledBorder("Edit links"));
999     GridBagConstraints gbc = new GridBagConstraints();
1000     gbc.gridx = 0;
1001     gbc.gridy = 0;
1002     gbc.fill = GridBagConstraints.NONE;
1003     buttonPanel.add(newLink, gbc);
1004
1005     GridBagConstraints gbc1 = new GridBagConstraints();
1006     gbc1.gridx = 1;
1007     gbc1.gridy = 0;
1008     gbc1.fill = GridBagConstraints.NONE;
1009     buttonPanel.add(editLink, gbc1);
1010
1011     GridBagConstraints gbc2 = new GridBagConstraints();
1012     gbc2.gridx = 2;
1013     gbc2.gridy = 0;
1014     gbc2.fill = GridBagConstraints.NONE;
1015     buttonPanel.add(deleteLink, gbc2);
1016
1017     GridBagConstraints gbc3 = new GridBagConstraints();
1018     gbc3.gridx = 3;
1019     gbc3.gridy = 0;
1020     gbc3.fill = GridBagConstraints.HORIZONTAL;
1021     gbc3.weightx = 1.0;
1022     JPanel spacePanel = new JPanel();
1023     spacePanel.setBorder(null);
1024     buttonPanel.add(spacePanel, gbc3);
1025
1026     return buttonPanel;
1027   }
1028
1029   /**
1030    * Initialises the proxy server panel in the Connections tab
1031    * 
1032    * @return the proxy server panel
1033    */
1034   private JPanel initConnTabProxyPanel()
1035   {
1036     // Label for server text box
1037     serverLabel.setText(MessageManager.getString("label.address"));
1038     serverLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1039     serverLabel.setFont(LABEL_FONT);
1040
1041     // Proxy server and port text boxes
1042     proxyServerTB.setFont(LABEL_FONT);
1043     proxyPortTB.setFont(LABEL_FONT);
1044
1045     // Label for Port text box
1046     portLabel.setFont(LABEL_FONT);
1047     portLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1048     portLabel.setText(MessageManager.getString("label.port"));
1049
1050     // Use proxy server checkbox
1051     useProxy.setFont(LABEL_FONT);
1052     useProxy.setHorizontalAlignment(SwingConstants.RIGHT);
1053     useProxy.setHorizontalTextPosition(SwingConstants.LEADING);
1054     useProxy.setText(MessageManager.getString("label.use_proxy_server"));
1055     useProxy.addActionListener(new ActionListener()
1056     {
1057       @Override
1058       public void actionPerformed(ActionEvent e)
1059       {
1060         useProxy_actionPerformed();
1061       }
1062     });
1063
1064     // Make proxy server panel
1065     JPanel proxyPanel = new JPanel();
1066     TitledBorder titledBorder1 = new TitledBorder(
1067             MessageManager.getString("label.proxy_server"));
1068     proxyPanel.setBorder(titledBorder1);
1069     proxyPanel.setLayout(new GridBagLayout());
1070     proxyPanel.add(serverLabel,
1071             new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
1072                     GridBagConstraints.WEST, GridBagConstraints.NONE,
1073                     new Insets(0, 2, 2, 0), 5, 0));
1074     proxyPanel.add(portLabel,
1075             new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
1076                     GridBagConstraints.WEST, GridBagConstraints.NONE,
1077                     new Insets(0, 0, 2, 0), 11, 0));
1078     proxyPanel.add(useProxy,
1079             new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0,
1080                     GridBagConstraints.WEST, GridBagConstraints.NONE,
1081                     new Insets(0, 2, 5, 185), 2, -4));
1082     proxyPanel.add(proxyPortTB,
1083             new GridBagConstraints(3, 1, 1, 1, 1.0, 0.0,
1084                     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
1085                     new Insets(0, 2, 2, 2), 54, 1));
1086     proxyPanel.add(proxyServerTB,
1087             new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0,
1088                     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
1089                     new Insets(0, 2, 2, 0), 263, 1));
1090
1091     return proxyPanel;
1092   }
1093
1094   /**
1095    * Initialises the checkboxes in the Connections tab
1096    */
1097   private void initConnTabCheckboxes()
1098   {
1099     // Usage stats checkbox label
1100     usagestats.setText(
1101             MessageManager.getString("label.send_usage_statistics"));
1102     usagestats.setFont(LABEL_FONT);
1103     usagestats.setHorizontalAlignment(SwingConstants.RIGHT);
1104     usagestats.setHorizontalTextPosition(SwingConstants.LEADING);
1105
1106     // Questionnaire checkbox label
1107     questionnaire.setText(
1108             MessageManager.getString("label.check_for_questionnaires"));
1109     questionnaire.setFont(LABEL_FONT);
1110     questionnaire.setHorizontalAlignment(SwingConstants.RIGHT);
1111     questionnaire.setHorizontalTextPosition(SwingConstants.LEADING);
1112
1113     // Check for latest version checkbox label
1114     versioncheck.setText(
1115             MessageManager.getString("label.check_for_latest_version"));
1116     versioncheck.setFont(LABEL_FONT);
1117     versioncheck.setHorizontalAlignment(SwingConstants.RIGHT);
1118     versioncheck.setHorizontalTextPosition(SwingConstants.LEADING);
1119   }
1120
1121   /**
1122    * Initialises the parent panel which contains the tabbed sections.
1123    * 
1124    * @return
1125    */
1126   private JPanel initOkCancelPanel()
1127   {
1128     JButton ok = new JButton();
1129     ok.setText(MessageManager.getString("action.ok"));
1130     ok.addActionListener(new ActionListener()
1131     {
1132       @Override
1133       public void actionPerformed(ActionEvent e)
1134       {
1135         ok_actionPerformed(e);
1136       }
1137     });
1138     JButton cancel = new JButton();
1139     cancel.setText(MessageManager.getString("action.cancel"));
1140     cancel.addActionListener(new ActionListener()
1141     {
1142       @Override
1143       public void actionPerformed(ActionEvent e)
1144       {
1145         cancel_actionPerformed(e);
1146       }
1147     });
1148     JPanel okCancelPanel = new JPanel();
1149     okCancelPanel.add(ok);
1150     okCancelPanel.add(cancel);
1151     return okCancelPanel;
1152   }
1153
1154   /**
1155    * Initialises the Colours tabbed panel.
1156    * 
1157    * @return
1158    */
1159   private JPanel initColoursTab()
1160   {
1161     JPanel coloursTab = new JPanel();
1162     coloursTab.setBorder(new TitledBorder(
1163             MessageManager.getString("action.open_new_alignment")));
1164     coloursTab.setLayout(new FlowLayout());
1165     JLabel mincolourLabel = new JLabel();
1166     mincolourLabel.setFont(LABEL_FONT);
1167     mincolourLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1168     mincolourLabel.setText(MessageManager.getString("label.min_colour"));
1169     minColour.setFont(LABEL_FONT);
1170     minColour.setBorder(BorderFactory.createEtchedBorder());
1171     minColour.setPreferredSize(new Dimension(40, 20));
1172     minColour.addMouseListener(new MouseAdapter()
1173     {
1174       @Override
1175       public void mousePressed(MouseEvent e)
1176       {
1177         minColour_actionPerformed(minColour);
1178       }
1179     });
1180     JLabel maxcolourLabel = new JLabel();
1181     maxcolourLabel.setFont(LABEL_FONT);
1182     maxcolourLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1183     maxcolourLabel.setText(MessageManager.getString("label.max_colour"));
1184     maxColour.setFont(LABEL_FONT);
1185     maxColour.setBorder(BorderFactory.createEtchedBorder());
1186     maxColour.setPreferredSize(new Dimension(40, 20));
1187     maxColour.addMouseListener(new MouseAdapter()
1188     {
1189       @Override
1190       public void mousePressed(MouseEvent e)
1191       {
1192         maxColour_actionPerformed(maxColour);
1193       }
1194     });
1195
1196     protColour.setFont(LABEL_FONT);
1197     protColour.setBounds(new Rectangle(172, 225, 155, 21));
1198     JLabel protColourLabel = new JLabel();
1199     protColourLabel.setFont(LABEL_FONT);
1200     protColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
1201     protColourLabel.setText(
1202             MessageManager.getString("label.prot_alignment_colour") + " ");
1203     GPreferences.addtoLayout(coloursTab,
1204             MessageManager
1205                     .getString("label.default_colour_scheme_for_alignment"),
1206             protColourLabel, protColour);
1207
1208     nucColour.setFont(LABEL_FONT);
1209     nucColour.setBounds(new Rectangle(172, 240, 155, 21));
1210     JLabel nucColourLabel = new JLabel();
1211     nucColourLabel.setFont(LABEL_FONT);
1212     nucColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
1213     nucColourLabel.setText(
1214             MessageManager.getString("label.nuc_alignment_colour") + " ");
1215     GPreferences.addtoLayout(coloursTab,
1216             MessageManager
1217                     .getString("label.default_colour_scheme_for_alignment"),
1218             nucColourLabel, nucColour);
1219
1220     JPanel annotationShding = new JPanel();
1221     annotationShding.setBorder(new TitledBorder(
1222             MessageManager.getString("label.annotation_shading_default")));
1223     annotationShding.setLayout(new GridLayout(1, 2));
1224     GPreferences.addtoLayout(annotationShding,
1225             MessageManager.getString(
1226                     "label.default_minimum_colour_annotation_shading"),
1227             mincolourLabel, minColour);
1228     GPreferences.addtoLayout(annotationShding,
1229             MessageManager.getString(
1230                     "label.default_maximum_colour_annotation_shading"),
1231             maxcolourLabel, maxColour);
1232     coloursTab.add(annotationShding); // , FlowLayout.LEFT);
1233     return coloursTab;
1234   }
1235
1236   /**
1237    * Initialises the Overview tabbed panel.
1238    * 
1239    * @return
1240    */
1241   private JPanel initOverviewTab()
1242   {
1243     JPanel overviewPanel = new JPanel();
1244     overviewPanel.setBorder(new TitledBorder(
1245             MessageManager.getString("label.overview_settings")));
1246
1247     gapColour.setFont(LABEL_FONT);
1248     // fixing the border colours stops apparent colour bleed from the panel
1249     gapColour.setBorder(
1250             BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
1251     gapColour.setPreferredSize(new Dimension(40, 20));
1252     gapColour.addMouseListener(new MouseAdapter()
1253     {
1254       @Override
1255       public void mousePressed(MouseEvent e)
1256       {
1257         gapColour_actionPerformed(gapColour);
1258       }
1259     });
1260
1261     hiddenColour.setFont(LABEL_FONT);
1262     // fixing the border colours stops apparent colour bleed from the panel
1263     hiddenColour.setBorder(
1264             BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
1265     hiddenColour.setPreferredSize(new Dimension(40, 20));
1266     hiddenColour.addMouseListener(new MouseAdapter()
1267     {
1268       @Override
1269       public void mousePressed(MouseEvent e)
1270       {
1271         hiddenColour_actionPerformed(hiddenColour);
1272       }
1273     });
1274
1275     useLegacyGap = new JCheckBox(
1276             MessageManager.getString("label.ov_legacy_gap"));
1277     useLegacyGap.setFont(LABEL_FONT);
1278     useLegacyGap.setHorizontalAlignment(SwingConstants.LEFT);
1279     useLegacyGap.setVerticalTextPosition(SwingConstants.TOP);
1280     gapLabel = new JLabel(MessageManager.getString("label.gap_colour"));
1281     gapLabel.setFont(LABEL_FONT);
1282     gapLabel.setHorizontalAlignment(SwingConstants.LEFT);
1283     gapLabel.setVerticalTextPosition(SwingConstants.TOP);
1284     showHiddenAtStart = new JCheckBox(
1285             MessageManager.getString("label.ov_show_hide_default"));
1286     showHiddenAtStart.setFont(LABEL_FONT);
1287     showHiddenAtStart.setHorizontalAlignment(SwingConstants.LEFT);
1288     showHiddenAtStart.setVerticalTextPosition(SwingConstants.TOP);
1289     JLabel hiddenLabel = new JLabel(
1290             MessageManager.getString("label.hidden_colour"));
1291     hiddenLabel.setFont(LABEL_FONT);
1292     hiddenLabel.setHorizontalAlignment(SwingConstants.LEFT);
1293     hiddenLabel.setVerticalTextPosition(SwingConstants.TOP);
1294
1295     useLegacyGap.addActionListener(new ActionListener()
1296     {
1297       @Override
1298       public void actionPerformed(ActionEvent e)
1299       {
1300         useLegacyGaps_actionPerformed(e);
1301       }
1302     });
1303
1304     overviewPanel.setLayout(new GridBagLayout());
1305     GridBagConstraints c1 = new GridBagConstraints();
1306
1307     c1.fill = GridBagConstraints.HORIZONTAL;
1308     c1.gridx = 0;
1309     c1.gridy = 0;
1310     c1.weightx = 1;
1311     c1.ipady = 20;
1312     c1.anchor = GridBagConstraints.FIRST_LINE_START;
1313     overviewPanel.add(useLegacyGap, c1);
1314
1315     GridBagConstraints c2 = new GridBagConstraints();
1316     c2.fill = GridBagConstraints.HORIZONTAL;
1317     c2.gridx = 1;
1318     c2.gridy = 0;
1319     c2.insets = new Insets(0, 15, 0, 10);
1320     overviewPanel.add(gapLabel, c2);
1321
1322     GridBagConstraints c3 = new GridBagConstraints();
1323     c3.fill = GridBagConstraints.HORIZONTAL;
1324     c3.gridx = 2;
1325     c3.gridy = 0;
1326     c3.insets = new Insets(0, 0, 0, 15);
1327     overviewPanel.add(gapColour, c3);
1328
1329     GridBagConstraints c4 = new GridBagConstraints();
1330     c4.fill = GridBagConstraints.HORIZONTAL;
1331     c4.gridx = 0;
1332     c4.gridy = 1;
1333     c4.weightx = 1;
1334     overviewPanel.add(showHiddenAtStart, c4);
1335
1336     GridBagConstraints c5 = new GridBagConstraints();
1337     c5.fill = GridBagConstraints.HORIZONTAL;
1338     c5.gridx = 1;
1339     c5.gridy = 1;
1340     c5.insets = new Insets(0, 15, 0, 10);
1341     overviewPanel.add(hiddenLabel, c5);
1342
1343     GridBagConstraints c6 = new GridBagConstraints();
1344     c6.fill = GridBagConstraints.HORIZONTAL;
1345     c6.gridx = 2;
1346     c6.gridy = 1;
1347     c6.insets = new Insets(0, 0, 0, 15);
1348     overviewPanel.add(hiddenColour, c6);
1349
1350     JButton resetButton = new JButton(
1351             MessageManager.getString("label.reset_to_defaults"));
1352
1353     resetButton.addActionListener(new ActionListener()
1354     {
1355       @Override
1356       public void actionPerformed(ActionEvent e)
1357       {
1358         resetOvDefaults_actionPerformed(e);
1359       }
1360     });
1361
1362     GridBagConstraints c7 = new GridBagConstraints();
1363     c7.fill = GridBagConstraints.NONE;
1364     c7.gridx = 0;
1365     c7.gridy = 2;
1366     c7.insets = new Insets(10, 0, 0, 0);
1367     c7.anchor = GridBagConstraints.WEST;
1368     overviewPanel.add(resetButton, c7);
1369
1370     // Add padding so the panel doesn't look ridiculous
1371     JPanel spacePanel = new JPanel();
1372     overviewPanel.add(spacePanel,
1373             new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
1374                     GridBagConstraints.WEST, GridBagConstraints.BOTH,
1375                     new Insets(0, 0, 0, 5), 0, 0));
1376
1377     return overviewPanel;
1378   }
1379
1380   /**
1381    * Initialises the Structure tabbed panel.
1382    * 
1383    * @return
1384    */
1385   private JPanel initStructureTab()
1386   {
1387     structureTab = new JPanel();
1388
1389     structureTab.setBorder(new TitledBorder(
1390             MessageManager.getString("label.structure_options")));
1391     structureTab.setLayout(null);
1392     final int width = 400;
1393     final int height = 22;
1394     final int lineSpacing = 25;
1395     int ypos = 15;
1396
1397     structFromPdb.setFont(LABEL_FONT);
1398     structFromPdb
1399             .setText(MessageManager.getString("label.struct_from_pdb"));
1400     structFromPdb.setBounds(new Rectangle(5, ypos, width, height));
1401     structFromPdb.addActionListener(new ActionListener()
1402     {
1403       @Override
1404       public void actionPerformed(ActionEvent e)
1405       {
1406         boolean selected = structFromPdb.isSelected();
1407         // enable other options only when the first is checked
1408         useRnaView.setEnabled(selected);
1409         addSecondaryStructure.setEnabled(selected);
1410         addTempFactor.setEnabled(selected);
1411       }
1412     });
1413     structureTab.add(structFromPdb);
1414
1415     // indent checkboxes that are conditional on the first one
1416     ypos += lineSpacing;
1417     useRnaView.setFont(LABEL_FONT);
1418     useRnaView.setText(MessageManager.getString("label.use_rnaview"));
1419     useRnaView.setBounds(new Rectangle(25, ypos, width, height));
1420     structureTab.add(useRnaView);
1421
1422     ypos += lineSpacing;
1423     addSecondaryStructure.setFont(LABEL_FONT);
1424     addSecondaryStructure
1425             .setText(MessageManager.getString("label.autoadd_secstr"));
1426     addSecondaryStructure.setBounds(new Rectangle(25, ypos, width, height));
1427     structureTab.add(addSecondaryStructure);
1428
1429     ypos += lineSpacing;
1430     addTempFactor.setFont(LABEL_FONT);
1431     addTempFactor.setText(MessageManager.getString("label.autoadd_temp"));
1432     addTempFactor.setBounds(new Rectangle(25, ypos, width, height));
1433     structureTab.add(addTempFactor);
1434
1435     ypos += lineSpacing;
1436     JLabel viewerLabel = new JLabel();
1437     viewerLabel.setFont(LABEL_FONT);
1438     viewerLabel.setHorizontalAlignment(SwingConstants.LEFT);
1439     viewerLabel.setText(MessageManager.getString("label.structure_viewer"));
1440     viewerLabel.setBounds(new Rectangle(10, ypos, 200, height));
1441     structureTab.add(viewerLabel);
1442
1443     structViewer.setFont(LABEL_FONT);
1444     structViewer.setBounds(new Rectangle(160, ypos, 120, height));
1445     structViewer.addItem(ViewerType.JMOL.name());
1446     structViewer.addItem(ViewerType.CHIMERA.name());
1447     structViewer.addActionListener(new ActionListener()
1448     {
1449       @Override
1450       public void actionPerformed(ActionEvent e)
1451       {
1452         structureViewer_actionPerformed(
1453                 (String) structViewer.getSelectedItem());
1454       }
1455     });
1456     structureTab.add(structViewer);
1457
1458     ypos += lineSpacing;
1459     JLabel pathLabel = new JLabel();
1460     pathLabel.setFont(new java.awt.Font("SansSerif", 0, 11));
1461     pathLabel.setHorizontalAlignment(SwingConstants.LEFT);
1462     pathLabel.setText(MessageManager.getString("label.chimera_path"));
1463     pathLabel.setBounds(new Rectangle(10, ypos, 140, height));
1464     structureTab.add(pathLabel);
1465
1466     chimeraPath.setFont(LABEL_FONT);
1467     chimeraPath.setText("");
1468     final String tooltip = JvSwingUtils.wrapTooltip(true,
1469             MessageManager.getString("label.chimera_path_tip"));
1470     chimeraPath.setToolTipText(tooltip);
1471     chimeraPath.setBounds(new Rectangle(160, ypos, 300, height));
1472     chimeraPath.addMouseListener(new MouseAdapter()
1473     {
1474       @Override
1475       public void mouseClicked(MouseEvent e)
1476       {
1477         if (e.getClickCount() == 2)
1478         {
1479           String chosen = openFileChooser(false);
1480           if (chosen != null)
1481           {
1482             chimeraPath.setText(chosen);
1483           }
1484         }
1485       }
1486     });
1487     structureTab.add(chimeraPath);
1488
1489     ypos += lineSpacing;
1490     nwMapping.setFont(LABEL_FONT);
1491     nwMapping.setText(MessageManager.getString("label.nw_mapping"));
1492     siftsMapping.setFont(LABEL_FONT);
1493     siftsMapping.setText(MessageManager.getString("label.sifts_mapping"));
1494     mappingMethod.add(nwMapping);
1495     mappingMethod.add(siftsMapping);
1496     JPanel mappingPanel = new JPanel();
1497     mappingPanel.setFont(LABEL_FONT);
1498     TitledBorder mmTitledBorder = new TitledBorder(
1499             MessageManager.getString("label.mapping_method"));
1500     mmTitledBorder.setTitleFont(LABEL_FONT);
1501     mappingPanel.setBorder(mmTitledBorder);
1502     mappingPanel.setBounds(new Rectangle(10, ypos, 452, 45));
1503     // GridLayout mappingLayout = new GridLayout();
1504     mappingPanel.setLayout(new GridLayout());
1505     mappingPanel.add(nwMapping);
1506     mappingPanel.add(siftsMapping);
1507     structureTab.add(mappingPanel);
1508
1509     ypos += lineSpacing;
1510     ypos += lineSpacing;
1511     FTSDataColumnPreferences docFieldPref = new FTSDataColumnPreferences(
1512             PreferenceSource.PREFERENCES, PDBFTSRestClient.getInstance());
1513     docFieldPref.setBounds(new Rectangle(10, ypos, 450, 120));
1514     structureTab.add(docFieldPref);
1515
1516     /*
1517      * hide Chimera options in JalviewJS
1518      */
1519     if (Platform.isJS()) 
1520     {
1521       pathLabel.setVisible(false);
1522       chimeraPath.setVisible(false);
1523       viewerLabel.setVisible(false);
1524       structViewer.setVisible(false);
1525     }
1526     
1527     return structureTab;
1528   }
1529
1530   /**
1531    * Action on choosing a structure viewer from combobox options.
1532    * 
1533    * @param selectedItem
1534    */
1535   protected void structureViewer_actionPerformed(String selectedItem)
1536   {
1537   }
1538
1539   /**
1540    * Show a dialog for the user to choose a file. Returns the chosen path, or
1541    * null on Cancel.
1542    * 
1543    * @return
1544    */
1545   protected String openFileChooser(boolean forFolder)
1546   {
1547     String choice = null;
1548     JFileChooser chooser = new JFileChooser();
1549     if (forFolder)
1550     {
1551       chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1552     }
1553
1554     // chooser.setFileView(new JalviewFileView());
1555     chooser.setDialogTitle(
1556             MessageManager.getString("label.open_local_file"));
1557     chooser.setToolTipText(MessageManager.getString("action.open"));
1558
1559     int value = chooser.showOpenDialog(this);
1560
1561     if (value == JFileChooser.APPROVE_OPTION)
1562     {
1563       choice = chooser.getSelectedFile().getPath();
1564     }
1565     return choice;
1566   }
1567
1568   protected boolean validateStructure()
1569   {
1570     return false;
1571   }
1572
1573   /**
1574    * Initialises the Visual tabbed panel.
1575    * 
1576    * @return
1577    */
1578   private JPanel initVisualTab()
1579   {
1580     JPanel visualTab = new JPanel();
1581     visualTab.setBorder(new TitledBorder(
1582             MessageManager.getString("action.open_new_alignment")));
1583     visualTab.setLayout(null);
1584     fullScreen.setFont(LABEL_FONT);
1585     fullScreen.setHorizontalAlignment(SwingConstants.RIGHT);
1586     fullScreen.setHorizontalTextPosition(SwingConstants.LEFT);
1587     fullScreen.setText(MessageManager.getString("label.maximize_window"));
1588     quality.setEnabled(false);
1589     quality.setFont(LABEL_FONT);
1590     quality.setHorizontalAlignment(SwingConstants.RIGHT);
1591     quality.setHorizontalTextPosition(SwingConstants.LEFT);
1592     quality.setSelected(true);
1593     quality.setText(MessageManager.getString("label.quality"));
1594     conservation.setEnabled(false);
1595     conservation.setFont(LABEL_FONT);
1596     conservation.setHorizontalAlignment(SwingConstants.RIGHT);
1597     conservation.setHorizontalTextPosition(SwingConstants.LEFT);
1598     conservation.setSelected(true);
1599     conservation.setText(MessageManager.getString("label.conservation"));
1600     identity.setEnabled(false);
1601     identity.setFont(LABEL_FONT);
1602     identity.setHorizontalAlignment(SwingConstants.RIGHT);
1603     identity.setHorizontalTextPosition(SwingConstants.LEFT);
1604     identity.setSelected(true);
1605     identity.setText(MessageManager.getString("label.consensus"));
1606     showOccupancy.setFont(LABEL_FONT);
1607     showOccupancy.setEnabled(false);
1608     showOccupancy.setHorizontalAlignment(SwingConstants.RIGHT);
1609     showOccupancy.setHorizontalTextPosition(SwingConstants.LEFT);
1610     showOccupancy.setSelected(true);
1611     showOccupancy.setText(MessageManager.getString("label.occupancy"));
1612
1613     JLabel showGroupbits = new JLabel();
1614     showGroupbits.setFont(LABEL_FONT);
1615     showGroupbits.setHorizontalAlignment(SwingConstants.RIGHT);
1616     showGroupbits.setHorizontalTextPosition(SwingConstants.LEFT);
1617     showGroupbits
1618             .setText(MessageManager.getString("action.show_group") + ":");
1619     JLabel showConsensbits = new JLabel();
1620     showConsensbits.setFont(LABEL_FONT);
1621     showConsensbits.setHorizontalAlignment(SwingConstants.RIGHT);
1622     showConsensbits.setHorizontalTextPosition(SwingConstants.LEFT);
1623     showConsensbits
1624             .setText(MessageManager.getString("label.consensus") + ":");
1625     showConsensHistogram.setEnabled(false);
1626     showConsensHistogram.setFont(LABEL_FONT);
1627     showConsensHistogram.setHorizontalAlignment(SwingConstants.RIGHT);
1628     showConsensHistogram.setHorizontalTextPosition(SwingConstants.LEFT);
1629     showConsensHistogram.setSelected(true);
1630     showConsensHistogram
1631             .setText(MessageManager.getString("label.histogram"));
1632     showConsensLogo.setEnabled(false);
1633     showConsensLogo.setFont(LABEL_FONT);
1634     showConsensLogo.setHorizontalAlignment(SwingConstants.RIGHT);
1635     showConsensLogo.setHorizontalTextPosition(SwingConstants.LEFT);
1636     showConsensLogo.setSelected(true);
1637     showConsensLogo.setText(MessageManager.getString("label.logo"));
1638     showGroupConsensus.setEnabled(false);
1639     showGroupConsensus.setFont(LABEL_FONT);
1640     showGroupConsensus.setHorizontalAlignment(SwingConstants.RIGHT);
1641     showGroupConsensus.setHorizontalTextPosition(SwingConstants.LEFT);
1642     showGroupConsensus.setSelected(true);
1643     showGroupConsensus.setText(MessageManager.getString("label.consensus"));
1644     showGroupConservation.setEnabled(false);
1645     showGroupConservation.setFont(LABEL_FONT);
1646     showGroupConservation.setHorizontalAlignment(SwingConstants.RIGHT);
1647     showGroupConservation.setHorizontalTextPosition(SwingConstants.LEFT);
1648     showGroupConservation.setSelected(true);
1649     showGroupConservation
1650             .setText(MessageManager.getString("label.conservation"));
1651     showNpTooltip.setEnabled(true);
1652     showNpTooltip.setFont(LABEL_FONT);
1653     showNpTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
1654     showNpTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
1655     showNpTooltip.setSelected(true);
1656     showNpTooltip.setText(
1657             MessageManager.getString("label.non_positional_features"));
1658     showDbRefTooltip.setEnabled(true);
1659     showDbRefTooltip.setFont(LABEL_FONT);
1660     showDbRefTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
1661     showDbRefTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
1662     showDbRefTooltip.setSelected(true);
1663     showDbRefTooltip
1664             .setText(MessageManager.getString("label.database_references"));
1665     annotations.setFont(LABEL_FONT);
1666     annotations.setHorizontalAlignment(SwingConstants.RIGHT);
1667     annotations.setHorizontalTextPosition(SwingConstants.LEFT);
1668     annotations.setSelected(true);
1669     annotations.setText(MessageManager.getString("label.show_annotations"));
1670     // annotations.setBounds(new Rectangle(169, 12, 200, 23));
1671     annotations.addActionListener(new ActionListener()
1672     {
1673       @Override
1674       public void actionPerformed(ActionEvent e)
1675       {
1676         annotations_actionPerformed(e);
1677       }
1678     });
1679     identity.addActionListener(new ActionListener()
1680     {
1681       @Override
1682       public void actionPerformed(ActionEvent e)
1683       {
1684         annotations_actionPerformed(e);
1685       }
1686     });
1687     showGroupConsensus.addActionListener(new ActionListener()
1688     {
1689       @Override
1690       public void actionPerformed(ActionEvent e)
1691       {
1692         annotations_actionPerformed(e);
1693       }
1694     });
1695     showUnconserved.setFont(LABEL_FONT);
1696     showUnconserved.setHorizontalAlignment(SwingConstants.RIGHT);
1697     showUnconserved.setHorizontalTextPosition(SwingConstants.LEFT);
1698     showUnconserved.setSelected(true);
1699     showUnconserved
1700             .setText(MessageManager.getString("action.show_unconserved"));
1701     showUnconserved.addActionListener(new ActionListener()
1702     {
1703       @Override
1704       public void actionPerformed(ActionEvent e)
1705       {
1706         showunconserved_actionPerformed(e);
1707       }
1708     });
1709
1710     // TODO these are not yet added to / action from Preferences
1711     // JCheckBox shareSelections = new JCheckBox();
1712     // shareSelections.setFont(verdana11);
1713     // shareSelections.setHorizontalAlignment(SwingConstants.RIGHT);
1714     // shareSelections.setHorizontalTextPosition(SwingConstants.LEFT);
1715     // shareSelections.setSelected(true);
1716     // shareSelections.setText(MessageManager
1717     // .getString("label.share_selection_across_views"));
1718     // JCheckBox followHighlight = new JCheckBox();
1719     // followHighlight.setFont(verdana11);
1720     // followHighlight.setHorizontalAlignment(SwingConstants.RIGHT);
1721     // followHighlight.setHorizontalTextPosition(SwingConstants.LEFT);
1722     // // showUnconserved.setBounds(new Rectangle(169, 40, 200, 23));
1723     // followHighlight.setSelected(true);
1724     // followHighlight.setText(MessageManager
1725     // .getString("label.scroll_highlighted_regions"));
1726
1727     seqLimit.setFont(LABEL_FONT);
1728     seqLimit.setHorizontalAlignment(SwingConstants.RIGHT);
1729     seqLimit.setHorizontalTextPosition(SwingConstants.LEFT);
1730     seqLimit.setText(MessageManager.getString("label.full_sequence_id"));
1731     smoothFont.setFont(LABEL_FONT);
1732     smoothFont.setHorizontalAlignment(SwingConstants.RIGHT);
1733     smoothFont.setHorizontalTextPosition(SwingConstants.LEADING);
1734     smoothFont.setText(MessageManager.getString("label.smooth_font"));
1735     scaleProteinToCdna.setFont(LABEL_FONT);
1736     scaleProteinToCdna.setHorizontalAlignment(SwingConstants.RIGHT);
1737     scaleProteinToCdna.setHorizontalTextPosition(SwingConstants.LEADING);
1738     scaleProteinToCdna.setText(
1739             MessageManager.getString("label.scale_protein_to_cdna"));
1740     scaleProteinToCdna.setToolTipText(
1741             MessageManager.getString("label.scale_protein_to_cdna_tip"));
1742     JLabel gapLabel = new JLabel();
1743     gapLabel.setFont(LABEL_FONT);
1744     gapLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1745     gapLabel.setText(MessageManager.getString("label.gap_symbol") + " ");
1746     JLabel fontLabel = new JLabel();
1747     fontLabel.setFont(LABEL_FONT);
1748     fontLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1749     fontLabel.setText(MessageManager.getString("label.font"));
1750     fontSizeCB.setFont(LABEL_FONT);
1751     fontSizeCB.setBounds(new Rectangle(320, 112, 65, 23));
1752     fontStyleCB.setFont(LABEL_FONT);
1753     fontStyleCB.setBounds(new Rectangle(382, 112, 80, 23));
1754     fontNameCB.setFont(LABEL_FONT);
1755     fontNameCB.setBounds(new Rectangle(172, 112, 147, 23));
1756     gapSymbolCB.setFont(LABEL_FONT);
1757     gapSymbolCB.setBounds(new Rectangle(172, 215, 69, 23));
1758     DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
1759     dlcr.setHorizontalAlignment(DefaultListCellRenderer.CENTER);
1760     gapSymbolCB.setRenderer(dlcr);
1761
1762     startupCheckbox.setText(MessageManager.getString("action.open_file"));
1763     startupCheckbox.setFont(LABEL_FONT);
1764     startupCheckbox.setHorizontalAlignment(SwingConstants.RIGHT);
1765     startupCheckbox.setHorizontalTextPosition(SwingConstants.LEFT);
1766     startupCheckbox.setSelected(true);
1767     startupFileTextfield.setFont(LABEL_FONT);
1768     startupFileTextfield.setBounds(new Rectangle(172, 310, 330, 20));
1769     final String tooltip = JvSwingUtils.wrapTooltip(true,
1770             MessageManager.getString("label.double_click_to_browse"));
1771     startupFileTextfield.setToolTipText(tooltip);
1772     startupFileTextfield.addMouseListener(new MouseAdapter()
1773     {
1774       @Override
1775       public void mouseClicked(MouseEvent e)
1776       {
1777         if (e.getClickCount() > 1)
1778         {
1779           startupFileTextfield_mouseClicked();
1780         }
1781       }
1782     });
1783
1784     sortby.setFont(LABEL_FONT);
1785     sortby.setBounds(new Rectangle(172, 260, 155, 21));
1786     JLabel sortLabel = new JLabel();
1787     sortLabel.setFont(LABEL_FONT);
1788     sortLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1789     sortLabel.setText(MessageManager.getString("label.sort_by"));
1790     sortAnnBy.setFont(LABEL_FONT);
1791     sortAnnBy.setBounds(new Rectangle(172, 285, 110, 21));
1792     JLabel sortAnnLabel = new JLabel();
1793     sortAnnLabel.setFont(LABEL_FONT);
1794     sortAnnLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1795     sortAnnLabel.setText(MessageManager.getString("label.sort_ann_by"));
1796     sortAutocalc.setFont(LABEL_FONT);
1797     sortAutocalc.setBounds(new Rectangle(290, 285, 165, 21));
1798
1799     JPanel annsettingsPanel = new JPanel();
1800     annsettingsPanel.setBounds(new Rectangle(173, 13, 320, 96));
1801     annsettingsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
1802     annsettingsPanel.setBorder(new EtchedBorder());
1803     visualTab.add(annsettingsPanel);
1804     Border jb = new EmptyBorder(1, 1, 4, 5);
1805     annotations.setBorder(jb);
1806     showOccupancy.setBorder(jb);
1807     quality.setBorder(jb);
1808     conservation.setBorder(jb);
1809     identity.setBorder(jb);
1810     showConsensbits.setBorder(jb);
1811     showGroupbits.setBorder(jb);
1812     showGroupConsensus.setBorder(jb);
1813     showGroupConservation.setBorder(jb);
1814     showConsensHistogram.setBorder(jb);
1815     showConsensLogo.setBorder(jb);
1816
1817     JPanel autoAnnotSettings = new JPanel();
1818     annsettingsPanel.add(autoAnnotSettings);
1819     autoAnnotSettings.setLayout(new GridLayout(0, 2));
1820     autoAnnotSettings.add(annotations);
1821     autoAnnotSettings.add(quality);
1822     // second row of autoannotation box
1823     autoAnnotSettings = new JPanel();
1824     annsettingsPanel.add(autoAnnotSettings);
1825
1826     autoAnnotSettings.setLayout(new GridLayout(0, 3));
1827     autoAnnotSettings.add(conservation);
1828     autoAnnotSettings.add(identity);
1829     autoAnnotSettings.add(showOccupancy);
1830     autoAnnotSettings.add(showGroupbits);
1831     autoAnnotSettings.add(showGroupConservation);
1832     autoAnnotSettings.add(showGroupConsensus);
1833     autoAnnotSettings.add(showConsensbits);
1834     autoAnnotSettings.add(showConsensHistogram);
1835     autoAnnotSettings.add(showConsensLogo);
1836
1837     JPanel tooltipSettings = new JPanel();
1838     tooltipSettings.setBorder(new TitledBorder(
1839             MessageManager.getString("label.sequence_id_tooltip")));
1840     tooltipSettings.setBounds(173, 140, 220, 62);
1841     tooltipSettings.setLayout(new GridLayout(2, 1));
1842     tooltipSettings.add(showDbRefTooltip);
1843     tooltipSettings.add(showNpTooltip);
1844     visualTab.add(tooltipSettings);
1845
1846     wrap.setFont(LABEL_FONT);
1847     wrap.setHorizontalAlignment(SwingConstants.TRAILING);
1848     wrap.setHorizontalTextPosition(SwingConstants.LEADING);
1849     wrap.setText(MessageManager.getString("label.wrap_alignment"));
1850     rightAlign.setFont(LABEL_FONT);
1851     rightAlign.setForeground(Color.black);
1852     rightAlign.setHorizontalAlignment(SwingConstants.RIGHT);
1853     rightAlign.setHorizontalTextPosition(SwingConstants.LEFT);
1854     rightAlign.setText(MessageManager.getString("label.right_align_ids"));
1855     idItalics.setFont(LABEL_FONT_ITALIC);
1856     idItalics.setHorizontalAlignment(SwingConstants.RIGHT);
1857     idItalics.setHorizontalTextPosition(SwingConstants.LEADING);
1858     idItalics.setText(
1859             MessageManager.getString("label.sequence_name_italics"));
1860     openoverv.setFont(LABEL_FONT);
1861     openoverv.setActionCommand(
1862             MessageManager.getString("label.open_overview"));
1863     openoverv.setHorizontalAlignment(SwingConstants.RIGHT);
1864     openoverv.setHorizontalTextPosition(SwingConstants.LEFT);
1865     openoverv.setText(MessageManager.getString("label.open_overview"));
1866     JPanel jPanel2 = new JPanel();
1867     jPanel2.setBounds(new Rectangle(7, 17, 158, 310));
1868     jPanel2.setLayout(new GridLayout(14, 1));
1869     jPanel2.add(fullScreen);
1870     jPanel2.add(openoverv);
1871     jPanel2.add(seqLimit);
1872     jPanel2.add(rightAlign);
1873     jPanel2.add(fontLabel);
1874     jPanel2.add(showUnconserved);
1875     jPanel2.add(idItalics);
1876     jPanel2.add(smoothFont);
1877     jPanel2.add(scaleProteinToCdna);
1878     jPanel2.add(gapLabel);
1879     jPanel2.add(wrap);
1880     jPanel2.add(sortLabel);
1881     jPanel2.add(sortAnnLabel);
1882     jPanel2.add(startupCheckbox);
1883     visualTab.add(jPanel2);
1884     visualTab.add(startupFileTextfield);
1885     visualTab.add(sortby);
1886     visualTab.add(sortAnnBy);
1887     visualTab.add(sortAutocalc);
1888     visualTab.add(gapSymbolCB);
1889     visualTab.add(fontNameCB);
1890     visualTab.add(fontSizeCB);
1891     visualTab.add(fontStyleCB);
1892     
1893     if (Platform.isJS())
1894     {
1895       startupCheckbox.setVisible(false);
1896       startupFileTextfield.setVisible(false);
1897     }
1898     
1899     return visualTab;
1900   }
1901
1902   /**
1903    * Load the saved Backups options EXCEPT "Enabled" and "Scheme"
1904    */
1905
1906   protected void loadLastSavedBackupsOptions()
1907   {
1908     BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry
1909             .getSavedBackupEntry();
1910     enableBackupFiles
1911             .setSelected(Cache.getDefault(BackupFiles.ENABLED, !Platform.isJS()));
1912
1913     BackupFilesPresetEntry backupfilesCustomEntry = BackupFilesPresetEntry
1914             .createBackupFilesPresetEntry(Cache
1915                     .getDefault(BackupFilesPresetEntry.CUSTOMCONFIG, null));
1916     if (backupfilesCustomEntry == null)
1917     {
1918       backupfilesCustomEntry = BackupFilesPresetEntry.backupfilesPresetEntriesValues
1919               .get(BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT);
1920     }
1921     BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
1922             BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM,
1923             backupfilesCustomEntry);
1924
1925     setComboIntStringKey(backupfilesPresetsCombo,
1926             Cache.getDefault(BackupFiles.NS + "_PRESET",
1927                     BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT));
1928
1929     backupsSetOptions(savedPreset);
1930
1931     backupsOptionsSetEnabled();
1932     updateBackupFilesExampleLabel();
1933   }
1934
1935   private boolean warnAboutSuffixReverseChange()
1936   {
1937     BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
1938             .getSavedBackupEntry();
1939     boolean savedSuffixReverse = bfpe.reverse;
1940     int savedSuffixDigits = bfpe.digits;
1941     String savedSuffixTemplate = bfpe.suffix;
1942
1943     boolean nowSuffixReverse = suffixReverse.isSelected();
1944     int nowSuffixDigits = getSpinnerInt(suffixDigitsSpinner, 3);
1945     String nowSuffixTemplate = suffixTemplate.getText();
1946     return nowSuffixReverse != savedSuffixReverse
1947             && nowSuffixDigits == savedSuffixDigits
1948             && nowSuffixTemplate != null
1949             && nowSuffixTemplate.equals(savedSuffixTemplate);
1950   }
1951
1952   /**
1953    * Initialises the Backups tabbed panel.
1954    * 
1955    * @return
1956    */
1957   private JPanel initBackupsTab()
1958   {
1959     JPanel backupsTab = new JPanel();
1960     backupsTab.setBorder(new TitledBorder(
1961             MessageManager.getString("label.backup_files")));
1962     backupsTab.setLayout(new GridBagLayout());
1963
1964     GridBagConstraints gbc = new GridBagConstraints();
1965     gbc.weightx = 0.0;
1966     gbc.weighty = 0.0;
1967     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
1968     gbc.fill = GridBagConstraints.NONE;
1969
1970     initBackupsTabPresetsPanel();
1971     initBackupsTabSuffixPanel();
1972     initBackupsTabKeepFilesPanel();
1973     initBackupsTabFilenameExamplesPanel();
1974
1975     enableBackupFiles.setFont(LABEL_FONT_BOLD);
1976     enableBackupFiles
1977             .setText(MessageManager.getString("label.enable_backupfiles"));
1978     enableBackupFiles.addActionListener(new ActionListener()
1979     {
1980       @Override
1981       public void actionPerformed(ActionEvent e)
1982       {
1983         // enable other options only when the first is checked
1984         backupsOptionsSetEnabled();
1985       }
1986     });
1987
1988
1989     // enable checkbox 1 col
1990     gbc.gridwidth = 1;
1991     gbc.gridheight = 1;
1992     gbc.gridx = 0;
1993     gbc.gridy = 0; // row 0
1994     backupsTab.add(enableBackupFiles, gbc);
1995
1996     // summary of scheme box (over two rows)
1997     gbc.gridx = 1;
1998     gbc.weightx = 0.0;
1999     gbc.gridheight = 2;
2000     gbc.anchor = GridBagConstraints.FIRST_LINE_END;
2001     gbc.fill = GridBagConstraints.BOTH;
2002     backupsTab.add(exampleFilesPanel, gbc);
2003     gbc.gridheight = 1;
2004     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
2005     gbc.fill = GridBagConstraints.NONE;
2006
2007     // fill empty space on right
2008     gbc.gridx++;
2009     gbc.weightx = 1.0;
2010     backupsTab.add(new JPanel(), gbc);
2011
2012     // schemes box
2013     gbc.weightx = 0.0;
2014     gbc.gridx = 0;
2015     gbc.gridy++; // row 1
2016     backupsTab.add(presetsPanel, gbc);
2017
2018     // now using whole row
2019     gbc.gridwidth = 2;
2020     gbc.gridheight = 1;
2021     // keep files box
2022     gbc.gridx = 0;
2023     gbc.gridy++; // row 2
2024     backupsTab.add(keepfilesPanel, gbc);
2025
2026     // filename strategy box
2027     gbc.gridy++; // row 3
2028     backupsTab.add(suffixPanel, gbc);
2029
2030     // fill empty space
2031     gbc.gridy++; // row 4
2032     gbc.weighty = 1.0;
2033     backupsTab.add(new JPanel(), gbc);
2034
2035     backupsOptionsSetEnabled();
2036     return backupsTab;
2037   }
2038
2039   private JPanel initBackupsTabPresetsPanel()
2040   {
2041
2042     String title = MessageManager.getString("label.schemes");
2043
2044     presetsPanel.setLayout(new GridBagLayout());
2045
2046     GridBagConstraints gbc = new GridBagConstraints();
2047     gbc.weightx = 0.0;
2048     gbc.weighty = 0.0;
2049     gbc.anchor = GridBagConstraints.BASELINE_LEADING;
2050     gbc.fill = GridBagConstraints.NONE;
2051     gbc.gridwidth = 1;
2052     gbc.gridheight = 1;
2053
2054     // "Scheme: "
2055     gbc.gridx = 0;
2056     gbc.gridy = 0;
2057
2058     presetsComboLabel = new JLabel(title + ":");
2059     presetsPanel.add(presetsComboLabel, gbc);
2060
2061     List<Object> entries = Arrays
2062             .asList((Object[]) BackupFilesPresetEntry.backupfilesPresetEntries);
2063     List<String> tooltips = Arrays.asList(
2064             BackupFilesPresetEntry.backupfilesPresetEntryDescriptions);
2065     backupfilesPresetsCombo = JvSwingUtils.buildComboWithTooltips(entries,
2066             tooltips);
2067     /*
2068     for (int i = 0; i < BackupFilesPresetEntry.backupfilesPresetEntries.length; i++)
2069     {
2070       backupfilesPresetsCombo
2071               .addItem(BackupFilesPresetEntry.backupfilesPresetEntries[i]);
2072     }
2073     */
2074
2075     backupfilesPresetsCombo.addActionListener(new ActionListener()
2076     {
2077       @Override
2078       public void actionPerformed(ActionEvent e)
2079       {
2080         int key = getComboIntStringKey(backupfilesPresetsCombo);
2081         if (!customiseCheckbox.isSelected())
2082         {
2083           backupfilesPresetsComboLastSelected = key;
2084         }
2085         if (key == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
2086         {
2087           if (customiseCheckbox.isSelected())
2088           {
2089             // got here by clicking on customiseCheckbox so don't change the values
2090             backupfilesCustomOptionsSetEnabled();
2091           }
2092           else
2093           {
2094             backupsTabUpdatePresets();
2095             backupfilesCustomOptionsSetEnabled();
2096           }
2097         }
2098         else
2099         {
2100           customiseCheckbox.setSelected(false);
2101           backupsTabUpdatePresets();
2102           backupfilesCustomOptionsSetEnabled();
2103         }
2104       }
2105     });
2106
2107     // dropdown list of preset schemes
2108     gbc.gridx = 1;
2109     presetsPanel.add(backupfilesPresetsCombo, gbc);
2110
2111     revertButton.setText(MessageManager.getString("label.cancel_changes"));
2112     revertButton.setToolTipText(
2113             MessageManager.getString("label.cancel_changes_description"));
2114     revertButton.addActionListener(new ActionListener()
2115     {
2116       @Override
2117       public void actionPerformed(ActionEvent e)
2118       {
2119         backupsSetOptions(
2120                 BackupFilesPresetEntry.backupfilesPresetEntriesValues.get(
2121                         BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM));
2122         backupfilesCustomOptionsSetEnabled();
2123       }
2124
2125     });
2126     revertButton.setFont(LABEL_FONT);
2127
2128     customiseCheckbox.setFont(LABEL_FONT);
2129     customiseCheckbox.setText(MessageManager.getString("label.customise"));
2130     customiseCheckbox.addActionListener(new ActionListener()
2131     {
2132       @Override
2133       public void actionPerformed(ActionEvent e)
2134       {
2135         int currently = getComboIntStringKey(backupfilesPresetsCombo);
2136         if (customiseCheckbox.isSelected())
2137         {
2138           backupfilesPresetsComboLastSelected = currently;
2139           setComboIntStringKey(backupfilesPresetsCombo,
2140                   BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
2141         }
2142         else
2143         {
2144           setComboIntStringKey(backupfilesPresetsCombo,
2145                   backupfilesPresetsComboLastSelected);
2146
2147         }
2148         backupfilesCustomOptionsSetEnabled();
2149       }
2150     });
2151     customiseCheckbox.setToolTipText(
2152             MessageManager.getString("label.customise_description"));
2153
2154     // customise checkbox
2155     gbc.gridx = 0;
2156     gbc.gridy++;
2157     presetsPanel.add(customiseCheckbox, gbc);
2158
2159     // "Cancel changes" button (aligned with combo box above)
2160     gbc.gridx = 1;
2161     presetsPanel.add(revertButton, gbc);
2162
2163     return presetsPanel;
2164   }
2165
2166   private JPanel initBackupsTabFilenameExamplesPanel()
2167   {
2168     String title = MessageManager
2169             .getString("label.scheme_examples");
2170     TitledBorder tb = new TitledBorder(title);
2171     exampleFilesPanel.setBorder(tb);
2172     exampleFilesPanel.setLayout(new GridBagLayout());
2173
2174
2175     backupfilesExampleLabel.setEditable(false);
2176     backupfilesExampleLabel
2177             .setBackground(exampleFilesPanel.getBackground());
2178
2179     updateBackupFilesExampleLabel();
2180
2181     GridBagConstraints gbc = new GridBagConstraints();
2182     gbc.weightx = 1.0;
2183     gbc.weighty = 1.0;
2184     gbc.fill = GridBagConstraints.NONE;
2185     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
2186
2187     exampleFilesPanel.add(backupfilesExampleLabel, gbc);
2188     return exampleFilesPanel;
2189   }
2190
2191   private void backupsTabUpdatePresets()
2192   {
2193     IntKeyStringValueEntry entry = (IntKeyStringValueEntry) backupfilesPresetsCombo
2194             .getSelectedItem();
2195     int key = entry.k;
2196     String value = entry.v;
2197
2198     if (BackupFilesPresetEntry.backupfilesPresetEntriesValues
2199             .containsKey(key))
2200     {
2201       backupsSetOptions(
2202               BackupFilesPresetEntry.backupfilesPresetEntriesValues
2203                       .get(key));
2204     }
2205     else
2206     {
2207       Cache.log.error(
2208               "Preset '" + value + "' [key:" + key + "] not implemented");
2209     }
2210
2211     // Custom options will now be enabled when the customiseCheckbox is checked
2212     // (performed above)
2213     // backupfilesCustomOptionsSetEnabled();
2214     updateBackupFilesExampleLabel();
2215   }
2216
2217   protected int getComboIntStringKey(
2218           JComboBox<Object> backupfilesPresetsCombo2)
2219   {
2220     IntKeyStringValueEntry e;
2221     try
2222     {
2223       e = (IntKeyStringValueEntry) backupfilesPresetsCombo2
2224               .getSelectedItem();
2225     } catch (Exception ex)
2226     {
2227       Cache.log.error(
2228               "Problem casting Combo entry to IntKeyStringValueEntry.");
2229       e = null;
2230     }
2231     return e != null ? e.k : 0;
2232   }
2233
2234   protected void setComboIntStringKey(
2235           JComboBox<Object> backupfilesPresetsCombo2,
2236           int key)
2237   {
2238     for (int i = 0; i < backupfilesPresetsCombo2.getItemCount(); i++)
2239     {
2240       IntKeyStringValueEntry e;
2241       try
2242       {
2243         e = (IntKeyStringValueEntry) backupfilesPresetsCombo2.getItemAt(i);
2244       } catch (Exception ex)
2245       {
2246         Cache.log.error(
2247                 "Problem casting Combo entry to IntKeyStringValueEntry. Skipping item. ");
2248         continue;
2249       }
2250       if (e.k == key)
2251       {
2252         backupfilesPresetsCombo2.setSelectedIndex(i);
2253         break;
2254       }
2255     }
2256     // backupsTabUpdatePresets();
2257   }
2258
2259   private JPanel initBackupsTabSuffixPanel()
2260   {
2261     suffixPanel.setBorder(new TitledBorder(
2262             MessageManager.getString("label.backup_filename_strategy")));
2263     suffixPanel.setLayout(new GridBagLayout());
2264
2265     suffixTemplateLabel
2266             .setText(MessageManager.getString("label.append_to_filename"));
2267     suffixTemplateLabel.setHorizontalAlignment(SwingConstants.LEFT);
2268     suffixTemplateLabel.setFont(LABEL_FONT);
2269
2270     final String tooltip = JvSwingUtils.wrapTooltip(true,
2271             MessageManager.getString("label.append_to_filename_tooltip"));
2272     suffixTemplate.setToolTipText(tooltip);
2273     suffixTemplate.addActionListener(new ActionListener()
2274     {
2275       @Override
2276       public void actionPerformed(ActionEvent e)
2277       {
2278         updateBackupFilesExampleLabel();
2279         backupfilesCustomOptionsSetEnabled();
2280         backupfilesRevertButtonSetEnabled(true);
2281       }
2282
2283     });
2284     suffixTemplate.addKeyListener(new KeyListener()
2285     {
2286       @Override
2287       public void keyReleased(KeyEvent e)
2288       {
2289         updateBackupFilesExampleLabel();
2290         backupfilesCustomOptionsSetEnabled();
2291         backupfilesRevertButtonSetEnabled(true);
2292       }
2293
2294       @Override
2295       public void keyPressed(KeyEvent e)
2296       {
2297       }
2298
2299       // disable use of ':' or '/' or '\'
2300       @Override
2301       public void keyTyped(KeyEvent e)
2302       {
2303         char c = e.getKeyChar();
2304         if (c == ':' || c == '/' || c == '\\')
2305         {
2306           // don't process ':' or '/' or '\'
2307           e.consume();
2308         }
2309       }
2310
2311     });
2312
2313     // digits spinner
2314     suffixDigitsLabel
2315             .setText(MessageManager.getString("label.index_digits"));
2316     suffixDigitsLabel.setHorizontalAlignment(SwingConstants.LEFT);
2317     suffixDigitsLabel.setFont(LABEL_FONT);
2318     ChangeListener c = new ChangeListener()
2319     {
2320       @Override
2321       public void stateChanged(ChangeEvent e)
2322       {
2323         backupfilesRevertButtonSetEnabled(true);
2324         updateBackupFilesExampleLabel();
2325       }
2326
2327     };
2328     setIntegerSpinner(suffixDigitsSpinner, BackupFilesPresetEntry.DIGITSMIN,
2329             BackupFilesPresetEntry.DIGITSMAX, 3, c);
2330
2331     suffixReverse.setLabels(MessageManager.getString("label.reverse_roll"),
2332             MessageManager.getString("label.increment_index"));
2333     suffixReverse.addActionListener(new ActionListener()
2334     {
2335       @Override
2336       public void actionPerformed(ActionEvent e)
2337       {
2338         boolean okay = true;
2339         if (warnAboutSuffixReverseChange())
2340         {
2341           // Warning popup
2342           okay = confirmSuffixReverseChange();
2343         }
2344         if (okay)
2345         {
2346           backupfilesRevertButtonSetEnabled(true);
2347           updateBackupFilesExampleLabel();
2348         }
2349         else
2350         {
2351           boolean savedSuffixReverse = BackupFilesPresetEntry
2352                   .getSavedBackupEntry().reverse;
2353           suffixReverse.setSelected(savedSuffixReverse);
2354         }
2355       }
2356     });
2357
2358     GridBagConstraints sgbc = new GridBagConstraints();
2359
2360     // first row (template text box)
2361     sgbc.anchor = GridBagConstraints.WEST;
2362     sgbc.gridx = 0;
2363     sgbc.gridy = 0;
2364     sgbc.gridwidth = 1;
2365     sgbc.gridheight = 1;
2366     sgbc.weightx = 1.0;
2367     sgbc.weighty = 0.0;
2368     sgbc.fill = GridBagConstraints.NONE;
2369     suffixPanel.add(suffixTemplateLabel, sgbc);
2370
2371     sgbc.gridx = 1;
2372     sgbc.fill = GridBagConstraints.HORIZONTAL;
2373     suffixPanel.add(suffixTemplate, sgbc);
2374
2375     // second row (number of digits spinner)
2376     sgbc.gridy = 1;
2377
2378     sgbc.gridx = 0;
2379     sgbc.fill = GridBagConstraints.NONE;
2380     suffixPanel.add(suffixDigitsLabel, sgbc);
2381
2382     sgbc.gridx = 1;
2383     sgbc.fill = GridBagConstraints.HORIZONTAL;
2384     suffixPanel.add(suffixDigitsSpinner, sgbc);
2385
2386     // third row (forward order radio selection)
2387     sgbc.gridx = 0;
2388     sgbc.gridy = 2;
2389     sgbc.gridwidth = GridBagConstraints.REMAINDER;
2390     sgbc.fill = GridBagConstraints.HORIZONTAL;
2391     suffixPanel.add(suffixReverse.getFalseButton(), sgbc);
2392
2393     // fourth row (reverse order radio selection)
2394     sgbc.gridy = 3;
2395     suffixPanel.add(suffixReverse.getTrueButton(), sgbc);
2396     return suffixPanel;
2397   }
2398
2399   private boolean confirmSuffixReverseChange()
2400   {
2401     boolean ret = false;
2402     String warningMessage = MessageManager
2403             .getString("label.warning_confirm_change_reverse");
2404     int confirm = JvOptionPane.showConfirmDialog(Desktop.desktop,
2405             warningMessage,
2406             MessageManager.getString("label.change_increment_decrement"),
2407             JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE);
2408
2409     ret = (confirm == JvOptionPane.YES_OPTION);
2410     return ret;
2411   }
2412
2413   private JPanel initBackupsTabKeepFilesPanel()
2414   {
2415     keepfilesPanel.setBorder(
2416             new TitledBorder(MessageManager.getString("label.keep_files")));
2417     keepfilesPanel.setLayout(new GridBagLayout());
2418
2419     backupfilesKeepAll.setLabels(
2420             MessageManager.getString("label.keep_all_backup_files"),
2421             MessageManager.getString(
2422                     "label.keep_only_this_number_of_backup_files"));
2423     backupfilesKeepAll.addTrueActionListener(new ActionListener()
2424     {
2425       @Override
2426       public void actionPerformed(ActionEvent e)
2427       {
2428         backupfilesRevertButtonSetEnabled(true);
2429         updateBackupFilesExampleLabel();
2430       }
2431     });
2432     backupfilesKeepAll.addActionListener(new ActionListener()
2433     {
2434       @Override
2435       public void actionPerformed(ActionEvent e)
2436       {
2437         backupfilesRevertButtonSetEnabled(true);
2438         keepRollMaxOptionsEnabled();
2439         updateBackupFilesExampleLabel();
2440       }
2441     });
2442
2443     ChangeListener c = new ChangeListener()
2444     {
2445       @Override
2446       public void stateChanged(ChangeEvent e)
2447       {
2448         backupfilesRevertButtonSetEnabled(true);
2449         updateBackupFilesExampleLabel();
2450       }
2451
2452     };
2453     setIntegerSpinner(backupfilesRollMaxSpinner,
2454             BackupFilesPresetEntry.ROLLMAXMIN,
2455             BackupFilesPresetEntry.ROLLMAXMAX, 4, true, c);
2456
2457     backupfilesConfirmDelete.setLabels(
2458             MessageManager.getString("label.always_ask"),
2459             MessageManager.getString("label.auto_delete"));
2460     backupfilesConfirmDelete.addActionListener(new ActionListener()
2461     {
2462       @Override
2463       public void actionPerformed(ActionEvent e)
2464       {
2465         backupfilesRevertButtonSetEnabled(true);
2466       }
2467     });
2468     // update the enabled section
2469     keepRollMaxOptionsEnabled();
2470
2471     GridBagConstraints kgbc = new GridBagConstraints();
2472
2473     // first row (template text box)
2474     kgbc.anchor = GridBagConstraints.WEST;
2475     kgbc.gridx = 0;
2476     kgbc.gridy = 0;
2477     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2478     kgbc.gridheight = 1;
2479     kgbc.weightx = 1.0;
2480     kgbc.weighty = 0.0;
2481     kgbc.fill = GridBagConstraints.HORIZONTAL;
2482     keepfilesPanel.add(backupfilesKeepAll.getTrueButton(), kgbc);
2483
2484     // second row
2485     kgbc.gridy = 1;
2486
2487     kgbc.gridx = 0;
2488     kgbc.gridwidth = GridBagConstraints.RELATIVE;
2489     keepfilesPanel.add(backupfilesKeepAll.getFalseButton(), kgbc);
2490
2491     kgbc.gridx = 1;
2492     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2493     keepfilesPanel.add(backupfilesRollMaxSpinner, kgbc);
2494
2495     // third row (indented)
2496     kgbc.gridy = 2;
2497     kgbc.insets = new Insets(0, 20, 0, 0);
2498
2499     kgbc.gridx = 0;
2500     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2501     kgbc.fill = GridBagConstraints.HORIZONTAL;
2502     kgbc.weightx = 1.0;
2503
2504     JPanel jp = new JPanel();
2505     jp.setLayout(new FlowLayout());
2506     oldBackupFilesLabel
2507             .setText(MessageManager
2508                     .getString("label.autodelete_old_backup_files"));
2509     oldBackupFilesLabel.setFont(LABEL_FONT);
2510     oldBackupFilesLabel.setHorizontalAlignment(SwingConstants.LEFT);
2511     jp.add(oldBackupFilesLabel);
2512     jp.add(backupfilesConfirmDelete.getTrueButton());
2513     jp.add(backupfilesConfirmDelete.getFalseButton());
2514     keepfilesPanel.add(jp, kgbc);
2515
2516     return keepfilesPanel;
2517   }
2518
2519   protected void updateBackupFilesExampleLabel()
2520   {
2521     int exampleindex = 12;
2522     String base = MessageManager.getString("label.filename") + ".fa";
2523     if (base == null || base.length() == 0)
2524     {
2525       base = "file_name.fa";
2526     }
2527
2528     boolean reverse = suffixReverse.isSelected();
2529     boolean keepAll = backupfilesKeepAll.isSelected();
2530     int rollMax = 4;
2531     String suffix = suffixTemplate.getText();
2532     int digits = 3;
2533
2534     backupfilesExampleLabel.setFont(LABEL_FONT_ITALIC);
2535     if (suffix == null || suffix.length() == 0)
2536     {
2537       backupfilesExampleLabel
2538               .setText(MessageManager.getString("label.no_backup_files"));
2539       backupfilesExampleLabel.setFont(LABEL_FONT_BOLD);
2540       return;
2541     }
2542
2543     rollMax = getSpinnerInt(backupfilesRollMaxSpinner, 4);
2544     rollMax = rollMax < 1 ? 1 : rollMax;
2545
2546     if (suffix.indexOf(BackupFiles.NUM_PLACEHOLDER) == -1)
2547     {
2548       rollMax = 1;
2549     }
2550
2551     digits = getSpinnerInt(suffixDigitsSpinner, 3);
2552     digits = digits < 1 ? 1 : digits;
2553
2554     int lowersurround = 2;
2555     int uppersurround = 0;
2556     StringBuilder exampleSB = new StringBuilder();
2557     boolean firstLine = true;
2558     int lineNumber = 0;
2559     if (reverse)
2560     {
2561
2562       int min = 1;
2563       int max = keepAll ? exampleindex : rollMax;
2564       for (int index = min; index <= max; index++)
2565       {
2566         if (index == min + lowersurround && index < max - uppersurround - 1)
2567         {
2568           exampleSB.append("\n...");
2569           lineNumber++;
2570         }
2571         else if (index > min + lowersurround && index < max - uppersurround)
2572         {
2573           // nothing
2574         }
2575         else
2576         {
2577           if (firstLine)
2578           {
2579             firstLine = false;
2580           }
2581           else
2582           {
2583             exampleSB.append("\n");
2584             lineNumber++;
2585           }
2586           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
2587                   base, suffix, digits));
2588           if (min == max)
2589           {
2590             // no extra text needed
2591           }
2592           else if (index == min)
2593           {
2594             String newest = MessageManager.getString("label.braced_newest");
2595             if (newest != null && newest.length() > 0)
2596             {
2597               exampleSB.append(" " + newest);
2598             }
2599           }
2600           else if (index == max)
2601           {
2602             String oldest = MessageManager.getString("label.braced_oldest");
2603             if (oldest != null && oldest.length() > 0)
2604             {
2605               exampleSB.append(" " + oldest);
2606             }
2607           }
2608         }
2609       }
2610     }
2611     else
2612     {
2613
2614       int min = (keepAll || exampleindex - rollMax < 0) ? 1
2615               : exampleindex - rollMax + 1;
2616       int max = exampleindex;
2617
2618       for (int index = min; index <= max; index++)
2619       {
2620
2621         if (index == min + lowersurround && index < max - uppersurround - 1)
2622         {
2623           exampleSB.append("\n...");
2624           lineNumber++;
2625         }
2626         else if (index > min + lowersurround && index < max - uppersurround)
2627         {
2628           // nothing
2629         }
2630         else
2631         {
2632           if (firstLine)
2633           {
2634             firstLine = false;
2635           }
2636           else
2637           {
2638             exampleSB.append("\n");
2639             lineNumber++;
2640           }
2641           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
2642                   base, suffix, digits));
2643           if (min == max)
2644           {
2645             // no extra text needed
2646           }
2647           else if (index == min)
2648           {
2649             String oldest = MessageManager.getString("label.braced_oldest");
2650             if (oldest != null && oldest.length() > 0)
2651             {
2652               exampleSB.append(" " + oldest);
2653             }
2654           }
2655           else if (index == max)
2656           {
2657             String newest = MessageManager.getString("label.braced_newest");
2658             if (newest != null && newest.length() > 0)
2659             {
2660               exampleSB.append(" " + newest);
2661             }
2662           }
2663         }
2664       }
2665
2666     }
2667
2668     // add some extra empty lines to pad out the example files box. ugh, please tell
2669     // me how to do this better
2670     int remainingLines = lowersurround + uppersurround + 1 - lineNumber;
2671     if (remainingLines > 0)
2672     {
2673       for (int i = 0; i < remainingLines; i++)
2674       {
2675         exampleSB.append("\n ");
2676         lineNumber++;
2677       }
2678     }
2679
2680     backupfilesExampleLabel.setText(exampleSB.toString());
2681   }
2682
2683   protected void setIntegerSpinner(JSpinner s, int min, int max, int def,
2684           boolean useExistingVal, ChangeListener c)
2685   {
2686     int i = def;
2687     if (useExistingVal)
2688     {
2689       try
2690       {
2691         i = ((Integer) s.getValue()).intValue();
2692       } catch (Exception e)
2693       {
2694         Cache.log.error(
2695                 "Exception casting the initial value of s.getValue()");
2696       }
2697     }
2698
2699     setIntegerSpinner(s, min, max, i, c);
2700   }
2701
2702   protected void setIntegerSpinner(JSpinner s, int min, int max, int def,
2703           ChangeListener c)
2704   {
2705     // integer spinner for number of digits
2706     if (def > max)
2707     {
2708       max = def;
2709     }
2710     if (def < min)
2711     {
2712       def = min;
2713     }
2714     SpinnerModel sModel = new SpinnerNumberModel(def, min, max, 1);
2715     s.setModel(sModel);
2716
2717     s.addChangeListener(c);
2718
2719   }
2720
2721   protected static int getSpinnerInt(JSpinner s, int def)
2722   {
2723     int i = def;
2724     try
2725     {
2726       s.commitEdit();
2727       i = (Integer) s.getValue();
2728     } catch (Exception e)
2729     {
2730       Cache.log.error("Failed casting (Integer) JSpinner s.getValue()");
2731     }
2732     return i;
2733   }
2734
2735   private void keepRollMaxOptionsEnabled()
2736   {
2737     boolean enabled = backupfilesKeepAll.isEnabled()
2738             && !backupfilesKeepAll.isSelected();
2739     oldBackupFilesLabel.setEnabled(enabled);
2740     backupfilesRollMaxSpinner.setEnabled(enabled);
2741     backupfilesConfirmDelete.setEnabled(enabled);
2742   }
2743
2744   private void backupfilesKeepAllSetEnabled(boolean tryEnabled)
2745   {
2746     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2747             && customiseCheckbox.isSelected()
2748             && suffixTemplate.getText()
2749                     .indexOf(BackupFiles.NUM_PLACEHOLDER) > -1;
2750     keepfilesPanel.setEnabled(enabled);
2751     backupfilesKeepAll.setEnabled(enabled);
2752     oldBackupFilesLabel.setEnabled(enabled);
2753     keepRollMaxOptionsEnabled();
2754   }
2755
2756   private void backupfilesSuffixTemplateDigitsSetEnabled()
2757   {
2758     boolean enabled = suffixTemplate.isEnabled() && suffixTemplate.getText()
2759             .indexOf(BackupFiles.NUM_PLACEHOLDER) > -1;
2760     suffixDigitsLabel.setEnabled(enabled);
2761     suffixDigitsSpinner.setEnabled(enabled);
2762     suffixReverse.setEnabled(enabled);
2763   }
2764
2765   private void backupfilesSuffixTemplateSetEnabled(boolean tryEnabled)
2766   {
2767     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2768             && customiseCheckbox.isSelected();
2769     suffixPanel.setEnabled(enabled);
2770     suffixTemplateLabel.setEnabled(enabled);
2771     suffixTemplate.setEnabled(enabled);
2772     backupfilesSuffixTemplateDigitsSetEnabled();
2773   }
2774
2775   private void backupfilesRevertButtonSetEnabled(boolean tryEnabled)
2776   {
2777     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2778             && customiseCheckbox.isSelected() && backupfilesCustomChanged();
2779     revertButton.setEnabled(enabled);
2780   }
2781
2782   private boolean backupfilesCustomChanged()
2783   {
2784     BackupFilesPresetEntry custom = BackupFilesPresetEntry.backupfilesPresetEntriesValues
2785             .get(BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
2786     BackupFilesPresetEntry current = getBackupfilesCurrentEntry();
2787     return !custom.equals(current);
2788   }
2789
2790   protected BackupFilesPresetEntry getBackupfilesCurrentEntry()
2791   {
2792     String suffix = suffixTemplate.getText();
2793     int digits = getSpinnerInt(suffixDigitsSpinner, 3);
2794     boolean reverse = suffixReverse.isSelected();
2795     boolean keepAll = backupfilesKeepAll.isSelected();
2796     int rollMax = getSpinnerInt(backupfilesRollMaxSpinner, 3);
2797     boolean confirmDelete = backupfilesConfirmDelete.isSelected();
2798
2799     BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits,
2800             reverse, keepAll, rollMax, confirmDelete);
2801
2802     return bfpe;
2803   }
2804
2805   protected void backupfilesCustomOptionsSetEnabled()
2806   {
2807     boolean enabled = customiseCheckbox.isSelected();
2808
2809     backupfilesRevertButtonSetEnabled(enabled);
2810     backupfilesSuffixTemplateSetEnabled(enabled);
2811     backupfilesKeepAllSetEnabled(enabled);
2812   }
2813
2814   private void backupfilesSummarySetEnabled()
2815   {
2816     boolean enabled = enableBackupFiles.isSelected();
2817     backupfilesExampleLabel.setEnabled(enabled);
2818     exampleFilesPanel.setEnabled(enabled);
2819   }
2820
2821   private void backupfilesPresetsSetEnabled()
2822   {
2823     boolean enabled = enableBackupFiles.isSelected();
2824     presetsPanel.setEnabled(enabled);
2825     presetsComboLabel.setEnabled(enabled);
2826     backupfilesPresetsCombo.setEnabled(enabled);
2827     customiseCheckbox.setEnabled(enabled);
2828     revertButton.setEnabled(enabled);
2829   }
2830
2831   protected void backupsOptionsSetEnabled()
2832   {
2833     backupfilesPresetsSetEnabled();
2834     backupfilesSummarySetEnabled();
2835     backupfilesCustomOptionsSetEnabled();
2836   }
2837
2838   protected void backupsSetOptions(String suffix, int digits,
2839           boolean reverse, boolean keepAll, int rollMax,
2840           boolean confirmDelete)
2841   {
2842     suffixTemplate.setText(suffix);
2843     suffixDigitsSpinner.setValue(digits);
2844     suffixReverse.setSelected(reverse);
2845     backupfilesKeepAll.setSelected(keepAll);
2846     backupfilesRollMaxSpinner.setValue(rollMax);
2847     backupfilesConfirmDelete.setSelected(confirmDelete);
2848   }
2849
2850   protected void backupsSetOptions(BackupFilesPresetEntry p)
2851   {
2852     backupsSetOptions(p.suffix, p.digits, p.reverse, p.keepAll, p.rollMax,
2853             p.confirmDelete);
2854   }
2855
2856   protected void autoIdWidth_actionPerformed()
2857   {
2858     // TODO Auto-generated method stub
2859
2860   }
2861
2862   protected void userIdWidth_actionPerformed()
2863   {
2864     // TODO Auto-generated method stub
2865
2866   }
2867
2868   protected void maxColour_actionPerformed(JPanel panel)
2869   {
2870   }
2871
2872   protected void minColour_actionPerformed(JPanel panel)
2873   {
2874   }
2875
2876   protected void gapColour_actionPerformed(JPanel panel)
2877   {
2878   }
2879
2880   protected void hiddenColour_actionPerformed(JPanel panel)
2881   {
2882   }
2883
2884   protected void showunconserved_actionPerformed(ActionEvent e)
2885   {
2886     // TODO Auto-generated method stub
2887
2888   }
2889
2890   protected void useLegacyGaps_actionPerformed(ActionEvent e)
2891   {
2892   }
2893
2894   protected void resetOvDefaults_actionPerformed(ActionEvent e)
2895   {
2896   }
2897
2898   /**
2899    * DOCUMENT ME!
2900    * 
2901    * @param e
2902    *          DOCUMENT ME!
2903    */
2904   public void ok_actionPerformed(ActionEvent e)
2905   {
2906   }
2907
2908   /**
2909    * DOCUMENT ME!
2910    * 
2911    * @param e
2912    *          DOCUMENT ME!
2913    */
2914   public void cancel_actionPerformed(ActionEvent e)
2915   {
2916   }
2917
2918   /**
2919    * DOCUMENT ME!
2920    * 
2921    * @param e
2922    *          DOCUMENT ME!
2923    */
2924   public void annotations_actionPerformed(ActionEvent e)
2925   {
2926   }
2927
2928   /**
2929    * DOCUMENT ME!
2930    */
2931   public void startupFileTextfield_mouseClicked()
2932   {
2933   }
2934
2935   public void newLink_actionPerformed(ActionEvent e)
2936   {
2937
2938   }
2939
2940   public void editLink_actionPerformed(ActionEvent e)
2941   {
2942
2943   }
2944
2945   public void deleteLink_actionPerformed(ActionEvent e)
2946   {
2947
2948   }
2949
2950   public void defaultBrowser_mouseClicked(MouseEvent e)
2951   {
2952
2953   }
2954
2955   public void linkURLList_keyTyped(KeyEvent e)
2956   {
2957
2958   }
2959
2960   public void useProxy_actionPerformed()
2961   {
2962     boolean enabled = useProxy.isSelected();
2963     portLabel.setEnabled(enabled);
2964     serverLabel.setEnabled(enabled);
2965     proxyServerTB.setEnabled(enabled);
2966     proxyPortTB.setEnabled(enabled);
2967   }
2968
2969   /**
2970    * Customer renderer for JTable: supports column of radio buttons
2971    */
2972   public class RadioButtonRenderer extends JRadioButton
2973           implements TableCellRenderer
2974   {
2975     public RadioButtonRenderer()
2976     {
2977       setHorizontalAlignment(CENTER);
2978       setToolTipText(MessageManager.getString("label.urltooltip"));
2979     }
2980
2981     @Override
2982     public Component getTableCellRendererComponent(JTable table,
2983             Object value, boolean isSelected, boolean hasFocus, int row,
2984             int column)
2985     {
2986       setSelected((boolean) value);
2987
2988       // set colours to match rest of table
2989       if (isSelected)
2990       {
2991         setBackground(table.getSelectionBackground());
2992         setForeground(table.getSelectionForeground());
2993       }
2994       else
2995       {
2996         setBackground(table.getBackground());
2997         setForeground(table.getForeground());
2998       }
2999       return this;
3000     }
3001   }
3002
3003   /**
3004    * Customer cell editor for JTable: supports column of radio buttons in
3005    * conjunction with renderer
3006    */
3007   public class RadioButtonEditor extends AbstractCellEditor
3008           implements TableCellEditor
3009   {
3010     private JRadioButton button = new JRadioButton();
3011
3012     public RadioButtonEditor()
3013     {
3014       button.setHorizontalAlignment(SwingConstants.CENTER);
3015       this.button.addActionListener(new ActionListener()
3016       {
3017         @Override
3018         public void actionPerformed(ActionEvent e)
3019         {
3020           fireEditingStopped();
3021         }
3022       });
3023     }
3024
3025     @Override
3026     public Component getTableCellEditorComponent(JTable table, Object value,
3027             boolean isSelected, int row, int column)
3028     {
3029       button.setSelected((boolean) value);
3030       return button;
3031     }
3032
3033     @Override
3034     public Object getCellEditorValue()
3035     {
3036       return button.isSelected();
3037     }
3038
3039   }
3040
3041   protected void validateHmmerPath()
3042   {
3043   }
3044
3045   protected void validateCygwinPath()
3046   {
3047   }
3048
3049   /**
3050    * A helper method to add a panel containing a label and a component to a
3051    * panel
3052    * 
3053    * @param panel
3054    * @param tooltip
3055    * @param label
3056    * @param valBox
3057    */
3058   protected static void addtoLayout(JPanel panel, String tooltip,
3059           JComponent label, JComponent valBox)
3060   {
3061     JPanel laypanel = new JPanel(new GridLayout(1, 2));
3062     JPanel labPanel = new JPanel(new BorderLayout());
3063     JPanel valPanel = new JPanel();
3064     labPanel.setBounds(new Rectangle(7, 7, 158, 23));
3065     valPanel.setBounds(new Rectangle(172, 7, 270, 23));
3066     labPanel.add(label, BorderLayout.WEST);
3067     valPanel.add(valBox);
3068     laypanel.add(labPanel);
3069     laypanel.add(valPanel);
3070     valPanel.setToolTipText(tooltip);
3071     labPanel.setToolTipText(tooltip);
3072     valBox.setToolTipText(tooltip);
3073     panel.add(laypanel);
3074     panel.validate();
3075   }
3076 }
3077