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