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