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