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