a366f33ab17bd4ece15ae71e2ace676b104ccbf2
[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     proxyAuthPasswordCheckHighlight(enabled, false);
1229   }
1230
1231   public void proxyAuthPasswordCheckHighlight(boolean enabled,
1232           boolean grabFocus)
1233   {
1234     if (enabled && proxyType.isSelected(customProxy.getModel())
1235             && proxyAuth.isSelected()
1236             && !proxyAuthUsernameTB.getText().isEmpty()
1237             && proxyAuthPasswordPB.getDocument().getLength() == 0)
1238     {
1239       if (grabFocus)
1240         proxyAuthPasswordPB.grabFocus();
1241       proxyAuthPasswordPB.setBackground(Color.PINK);
1242     }
1243     else
1244     {
1245       proxyAuthPasswordPB.setBackground(Color.WHITE);
1246     }
1247   }
1248
1249   public void applyProxyButtonEnabled(boolean enabled)
1250   {
1251     applyProxyButton.setEnabled(enabled);
1252   }
1253
1254   public void saveProxySettings()
1255   {
1256     // overridden in Preferences
1257   }
1258
1259   private String displayUserHostPort(String user, String host, String port)
1260   {
1261     boolean hostBlank = (host == null || host.isEmpty());
1262     boolean portBlank = (port == null || port.isEmpty());
1263     if (hostBlank && portBlank)
1264     {
1265       return MessageManager.getString("label.none");
1266     }
1267
1268     StringBuilder sb = new StringBuilder();
1269     if (user != null)
1270     {
1271       sb.append(user.isEmpty() || user.indexOf(" ") > -1 ? '"' + user + '"'
1272               : user);
1273       sb.append("@");
1274     }
1275     sb.append(hostBlank ? "" : host);
1276     if (!portBlank)
1277     {
1278       sb.append(":");
1279       sb.append(port);
1280     }
1281     return sb.toString();
1282   }
1283
1284   /**
1285    * Initialises the checkboxes in the Connections tab
1286    */
1287   private void initConnTabCheckboxes()
1288   {
1289     // Usage stats checkbox label
1290     usagestats.setText(
1291             MessageManager.getString("label.send_usage_statistics"));
1292     usagestats.setFont(LABEL_FONT);
1293     usagestats.setHorizontalAlignment(SwingConstants.RIGHT);
1294     usagestats.setHorizontalTextPosition(SwingConstants.LEADING);
1295
1296     // Questionnaire checkbox label
1297     questionnaire.setText(
1298             MessageManager.getString("label.check_for_questionnaires"));
1299     questionnaire.setFont(LABEL_FONT);
1300     questionnaire.setHorizontalAlignment(SwingConstants.RIGHT);
1301     questionnaire.setHorizontalTextPosition(SwingConstants.LEADING);
1302
1303     // Check for latest version checkbox label
1304     versioncheck.setText(
1305             MessageManager.getString("label.check_for_latest_version"));
1306     versioncheck.setFont(LABEL_FONT);
1307     versioncheck.setHorizontalAlignment(SwingConstants.RIGHT);
1308     versioncheck.setHorizontalTextPosition(SwingConstants.LEADING);
1309   }
1310
1311   /**
1312    * Initialises the parent panel which contains the tabbed sections.
1313    * 
1314    * @return
1315    */
1316   private JPanel initOkCancelPanel()
1317   {
1318     JButton ok = new JButton();
1319     ok.setText(MessageManager.getString("action.ok"));
1320     ok.addActionListener(new ActionListener()
1321     {
1322       @Override
1323       public void actionPerformed(ActionEvent e)
1324       {
1325         ok_actionPerformed(e);
1326       }
1327     });
1328     JButton cancel = new JButton();
1329     cancel.setText(MessageManager.getString("action.cancel"));
1330     cancel.addActionListener(new ActionListener()
1331     {
1332       @Override
1333       public void actionPerformed(ActionEvent e)
1334       {
1335         cancel_actionPerformed(e);
1336       }
1337     });
1338     JPanel okCancelPanel = new JPanel();
1339     okCancelPanel.add(ok);
1340     okCancelPanel.add(cancel);
1341     return okCancelPanel;
1342   }
1343
1344   /**
1345    * Initialises the Colours tabbed panel.
1346    * 
1347    * @return
1348    */
1349   private JPanel initColoursTab()
1350   {
1351     JPanel coloursTab = new JPanel();
1352     coloursTab.setBorder(new TitledBorder(
1353             MessageManager.getString("action.open_new_alignment")));
1354     coloursTab.setLayout(new FlowLayout());
1355     JLabel mincolourLabel = new JLabel();
1356     mincolourLabel.setFont(LABEL_FONT);
1357     mincolourLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1358     mincolourLabel.setText(MessageManager.getString("label.min_colour"));
1359     minColour.setFont(LABEL_FONT);
1360     minColour.setBorder(BorderFactory.createEtchedBorder());
1361     minColour.setPreferredSize(new Dimension(40, 20));
1362     minColour.addMouseListener(new MouseAdapter()
1363     {
1364       @Override
1365       public void mousePressed(MouseEvent e)
1366       {
1367         minColour_actionPerformed(minColour);
1368       }
1369     });
1370     JLabel maxcolourLabel = new JLabel();
1371     maxcolourLabel.setFont(LABEL_FONT);
1372     maxcolourLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1373     maxcolourLabel.setText(MessageManager.getString("label.max_colour"));
1374     maxColour.setFont(LABEL_FONT);
1375     maxColour.setBorder(BorderFactory.createEtchedBorder());
1376     maxColour.setPreferredSize(new Dimension(40, 20));
1377     maxColour.addMouseListener(new MouseAdapter()
1378     {
1379       @Override
1380       public void mousePressed(MouseEvent e)
1381       {
1382         maxColour_actionPerformed(maxColour);
1383       }
1384     });
1385
1386     protColour.setFont(LABEL_FONT);
1387     protColour.setBounds(new Rectangle(172, 225, 155, 21));
1388     JLabel protColourLabel = new JLabel();
1389     protColourLabel.setFont(LABEL_FONT);
1390     protColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
1391     protColourLabel.setText(
1392             MessageManager.getString("label.prot_alignment_colour") + " ");
1393     JvSwingUtils.addtoLayout(coloursTab,
1394             MessageManager
1395                     .getString("label.default_colour_scheme_for_alignment"),
1396             protColourLabel, protColour);
1397
1398     nucColour.setFont(LABEL_FONT);
1399     nucColour.setBounds(new Rectangle(172, 240, 155, 21));
1400     JLabel nucColourLabel = new JLabel();
1401     nucColourLabel.setFont(LABEL_FONT);
1402     nucColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
1403     nucColourLabel.setText(
1404             MessageManager.getString("label.nuc_alignment_colour") + " ");
1405     JvSwingUtils.addtoLayout(coloursTab,
1406             MessageManager
1407                     .getString("label.default_colour_scheme_for_alignment"),
1408             nucColourLabel, nucColour);
1409
1410     JPanel annotationShding = new JPanel();
1411     annotationShding.setBorder(new TitledBorder(
1412             MessageManager.getString("label.annotation_shading_default")));
1413     annotationShding.setLayout(new GridLayout(1, 2));
1414     JvSwingUtils.addtoLayout(annotationShding,
1415             MessageManager.getString(
1416                     "label.default_minimum_colour_annotation_shading"),
1417             mincolourLabel, minColour);
1418     JvSwingUtils.addtoLayout(annotationShding,
1419             MessageManager.getString(
1420                     "label.default_maximum_colour_annotation_shading"),
1421             maxcolourLabel, maxColour);
1422     coloursTab.add(annotationShding); // , FlowLayout.LEFT);
1423     return coloursTab;
1424   }
1425
1426   /**
1427    * Initialises the Overview tabbed panel.
1428    * 
1429    * @return
1430    */
1431   private JPanel initOverviewTab()
1432   {
1433     JPanel overviewPanel = new JPanel();
1434     overviewPanel.setBorder(new TitledBorder(
1435             MessageManager.getString("label.overview_settings")));
1436
1437     gapColour.setFont(LABEL_FONT);
1438     // fixing the border colours stops apparent colour bleed from the panel
1439     gapColour.setBorder(
1440             BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
1441     gapColour.setPreferredSize(new Dimension(40, 20));
1442     gapColour.addMouseListener(new MouseAdapter()
1443     {
1444       @Override
1445       public void mousePressed(MouseEvent e)
1446       {
1447         gapColour_actionPerformed(gapColour);
1448       }
1449     });
1450
1451     hiddenColour.setFont(LABEL_FONT);
1452     // fixing the border colours stops apparent colour bleed from the panel
1453     hiddenColour.setBorder(
1454             BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
1455     hiddenColour.setPreferredSize(new Dimension(40, 20));
1456     hiddenColour.addMouseListener(new MouseAdapter()
1457     {
1458       @Override
1459       public void mousePressed(MouseEvent e)
1460       {
1461         hiddenColour_actionPerformed(hiddenColour);
1462       }
1463     });
1464
1465     useLegacyGap = new JCheckBox(
1466             MessageManager.getString("label.ov_legacy_gap"));
1467     useLegacyGap.setFont(LABEL_FONT);
1468     useLegacyGap.setHorizontalAlignment(SwingConstants.LEFT);
1469     useLegacyGap.setVerticalTextPosition(SwingConstants.TOP);
1470     gapLabel = new JLabel(MessageManager.getString("label.gap_colour"));
1471     gapLabel.setFont(LABEL_FONT);
1472     gapLabel.setHorizontalAlignment(SwingConstants.LEFT);
1473     gapLabel.setVerticalTextPosition(SwingConstants.TOP);
1474     showHiddenAtStart = new JCheckBox(
1475             MessageManager.getString("label.ov_show_hide_default"));
1476     showHiddenAtStart.setFont(LABEL_FONT);
1477     showHiddenAtStart.setHorizontalAlignment(SwingConstants.LEFT);
1478     showHiddenAtStart.setVerticalTextPosition(SwingConstants.TOP);
1479     JLabel hiddenLabel = new JLabel(
1480             MessageManager.getString("label.hidden_colour"));
1481     hiddenLabel.setFont(LABEL_FONT);
1482     hiddenLabel.setHorizontalAlignment(SwingConstants.LEFT);
1483     hiddenLabel.setVerticalTextPosition(SwingConstants.TOP);
1484
1485     useLegacyGap.addActionListener(new ActionListener()
1486     {
1487       @Override
1488       public void actionPerformed(ActionEvent e)
1489       {
1490         useLegacyGaps_actionPerformed(e);
1491       }
1492     });
1493
1494     overviewPanel.setLayout(new GridBagLayout());
1495     GridBagConstraints c1 = new GridBagConstraints();
1496
1497     c1.fill = GridBagConstraints.HORIZONTAL;
1498     c1.gridx = 0;
1499     c1.gridy = 0;
1500     c1.weightx = 1;
1501     c1.ipady = 20;
1502     c1.anchor = GridBagConstraints.FIRST_LINE_START;
1503     overviewPanel.add(useLegacyGap, c1);
1504
1505     GridBagConstraints c2 = new GridBagConstraints();
1506     c2.fill = GridBagConstraints.HORIZONTAL;
1507     c2.gridx = 1;
1508     c2.gridy = 0;
1509     c2.insets = new Insets(0, 15, 0, 10);
1510     overviewPanel.add(gapLabel, c2);
1511
1512     GridBagConstraints c3 = new GridBagConstraints();
1513     c3.fill = GridBagConstraints.HORIZONTAL;
1514     c3.gridx = 2;
1515     c3.gridy = 0;
1516     c3.insets = new Insets(0, 0, 0, 15);
1517     overviewPanel.add(gapColour, c3);
1518
1519     GridBagConstraints c4 = new GridBagConstraints();
1520     c4.fill = GridBagConstraints.HORIZONTAL;
1521     c4.gridx = 0;
1522     c4.gridy = 1;
1523     c4.weightx = 1;
1524     overviewPanel.add(showHiddenAtStart, c4);
1525
1526     GridBagConstraints c5 = new GridBagConstraints();
1527     c5.fill = GridBagConstraints.HORIZONTAL;
1528     c5.gridx = 1;
1529     c5.gridy = 1;
1530     c5.insets = new Insets(0, 15, 0, 10);
1531     overviewPanel.add(hiddenLabel, c5);
1532
1533     GridBagConstraints c6 = new GridBagConstraints();
1534     c6.fill = GridBagConstraints.HORIZONTAL;
1535     c6.gridx = 2;
1536     c6.gridy = 1;
1537     c6.insets = new Insets(0, 0, 0, 15);
1538     overviewPanel.add(hiddenColour, c6);
1539
1540     JButton resetButton = new JButton(
1541             MessageManager.getString("label.reset_to_defaults"));
1542
1543     resetButton.addActionListener(new ActionListener()
1544     {
1545       @Override
1546       public void actionPerformed(ActionEvent e)
1547       {
1548         resetOvDefaults_actionPerformed(e);
1549       }
1550     });
1551
1552     GridBagConstraints c7 = new GridBagConstraints();
1553     c7.fill = GridBagConstraints.NONE;
1554     c7.gridx = 0;
1555     c7.gridy = 2;
1556     c7.insets = new Insets(10, 0, 0, 0);
1557     c7.anchor = GridBagConstraints.WEST;
1558     overviewPanel.add(resetButton, c7);
1559
1560     // Add padding so the panel doesn't look ridiculous
1561     JPanel spacePanel = new JPanel();
1562     overviewPanel.add(spacePanel,
1563             new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
1564                     GridBagConstraints.WEST, GridBagConstraints.BOTH,
1565                     new Insets(0, 0, 0, 5), 0, 0));
1566
1567     return overviewPanel;
1568   }
1569
1570   /**
1571    * Initialises the Structure tabbed panel.
1572    * 
1573    * @return
1574    */
1575   private JPanel initStructureTab()
1576   {
1577     structureTab = new JPanel();
1578
1579     structureTab.setBorder(new TitledBorder(
1580             MessageManager.getString("label.structure_options")));
1581     structureTab.setLayout(null);
1582     final int width = 400;
1583     final int height = 22;
1584     final int lineSpacing = 25;
1585     int ypos = 15;
1586
1587     structFromPdb.setFont(LABEL_FONT);
1588     structFromPdb
1589             .setText(MessageManager.getString("label.struct_from_pdb"));
1590     structFromPdb.setBounds(new Rectangle(5, ypos, width, height));
1591     structFromPdb.addActionListener(new ActionListener()
1592     {
1593       @Override
1594       public void actionPerformed(ActionEvent e)
1595       {
1596         boolean selected = structFromPdb.isSelected();
1597         // enable other options only when the first is checked
1598         useRnaView.setEnabled(selected);
1599         addSecondaryStructure.setEnabled(selected);
1600         addTempFactor.setEnabled(selected);
1601       }
1602     });
1603     structureTab.add(structFromPdb);
1604
1605     // indent checkboxes that are conditional on the first one
1606     ypos += lineSpacing;
1607     useRnaView.setFont(LABEL_FONT);
1608     useRnaView.setText(MessageManager.getString("label.use_rnaview"));
1609     useRnaView.setBounds(new Rectangle(25, ypos, width, height));
1610     structureTab.add(useRnaView);
1611
1612     ypos += lineSpacing;
1613     addSecondaryStructure.setFont(LABEL_FONT);
1614     addSecondaryStructure
1615             .setText(MessageManager.getString("label.autoadd_secstr"));
1616     addSecondaryStructure.setBounds(new Rectangle(25, ypos, width, height));
1617     structureTab.add(addSecondaryStructure);
1618
1619     ypos += lineSpacing;
1620     addTempFactor.setFont(LABEL_FONT);
1621     addTempFactor.setText(MessageManager.getString("label.autoadd_temp"));
1622     addTempFactor.setBounds(new Rectangle(25, ypos, width, height));
1623     structureTab.add(addTempFactor);
1624
1625     ypos += lineSpacing;
1626     JLabel viewerLabel = new JLabel();
1627     viewerLabel.setFont(LABEL_FONT);
1628     viewerLabel.setHorizontalAlignment(SwingConstants.LEFT);
1629     viewerLabel.setText(MessageManager.getString("label.structure_viewer"));
1630     viewerLabel.setBounds(new Rectangle(10, ypos, 200, height));
1631     structureTab.add(viewerLabel);
1632
1633     structViewer.setFont(LABEL_FONT);
1634     structViewer.setBounds(new Rectangle(160, ypos, 120, height));
1635     structViewer.addItem(ViewerType.JMOL.name());
1636     structViewer.addItem(ViewerType.CHIMERA.name());
1637     structViewer.addActionListener(new ActionListener()
1638     {
1639       @Override
1640       public void actionPerformed(ActionEvent e)
1641       {
1642         structureViewer_actionPerformed(
1643                 (String) structViewer.getSelectedItem());
1644       }
1645     });
1646     structureTab.add(structViewer);
1647
1648     ypos += lineSpacing;
1649     JLabel pathLabel = new JLabel();
1650     pathLabel.setFont(new java.awt.Font("SansSerif", 0, 11));
1651     pathLabel.setHorizontalAlignment(SwingConstants.LEFT);
1652     pathLabel.setText(MessageManager.getString("label.chimera_path"));
1653     pathLabel.setBounds(new Rectangle(10, ypos, 140, height));
1654     structureTab.add(pathLabel);
1655
1656     chimeraPath.setFont(LABEL_FONT);
1657     chimeraPath.setText("");
1658     final String tooltip = JvSwingUtils.wrapTooltip(true,
1659             MessageManager.getString("label.chimera_path_tip"));
1660     chimeraPath.setToolTipText(tooltip);
1661     chimeraPath.setBounds(new Rectangle(160, ypos, 300, height));
1662     chimeraPath.addMouseListener(new MouseAdapter()
1663     {
1664       @Override
1665       public void mouseClicked(MouseEvent e)
1666       {
1667         if (e.getClickCount() == 2)
1668         {
1669           String chosen = openFileChooser();
1670           if (chosen != null)
1671           {
1672             chimeraPath.setText(chosen);
1673           }
1674         }
1675       }
1676     });
1677     structureTab.add(chimeraPath);
1678
1679     ypos += lineSpacing;
1680     nwMapping.setFont(LABEL_FONT);
1681     nwMapping.setText(MessageManager.getString("label.nw_mapping"));
1682     siftsMapping.setFont(LABEL_FONT);
1683     siftsMapping.setText(MessageManager.getString("label.sifts_mapping"));
1684     mappingMethod.add(nwMapping);
1685     mappingMethod.add(siftsMapping);
1686     JPanel mappingPanel = new JPanel();
1687     mappingPanel.setFont(LABEL_FONT);
1688     TitledBorder mmTitledBorder = new TitledBorder(
1689             MessageManager.getString("label.mapping_method"));
1690     mmTitledBorder.setTitleFont(LABEL_FONT);
1691     mappingPanel.setBorder(mmTitledBorder);
1692     mappingPanel.setBounds(new Rectangle(10, ypos, 452, 45));
1693     // GridLayout mappingLayout = new GridLayout();
1694     mappingPanel.setLayout(new GridLayout());
1695     mappingPanel.add(nwMapping);
1696     mappingPanel.add(siftsMapping);
1697     structureTab.add(mappingPanel);
1698
1699     ypos += lineSpacing;
1700     ypos += lineSpacing;
1701     FTSDataColumnPreferences docFieldPref = new FTSDataColumnPreferences(
1702             PreferenceSource.PREFERENCES, PDBFTSRestClient.getInstance());
1703     docFieldPref.setBounds(new Rectangle(10, ypos, 450, 120));
1704     structureTab.add(docFieldPref);
1705
1706     return structureTab;
1707   }
1708
1709   /**
1710    * Action on choosing a structure viewer from combobox options.
1711    * 
1712    * @param selectedItem
1713    */
1714   protected void structureViewer_actionPerformed(String selectedItem)
1715   {
1716   }
1717
1718   /**
1719    * Show a dialog for the user to choose a file. Returns the chosen path, or
1720    * null on Cancel.
1721    * 
1722    * @return
1723    */
1724   protected String openFileChooser()
1725   {
1726     String choice = null;
1727     JFileChooser chooser = new JFileChooser();
1728
1729     // chooser.setFileView(new JalviewFileView());
1730     chooser.setDialogTitle(
1731             MessageManager.getString("label.open_local_file"));
1732     chooser.setToolTipText(MessageManager.getString("action.open"));
1733
1734     int value = chooser.showOpenDialog(this);
1735
1736     if (value == JFileChooser.APPROVE_OPTION)
1737     {
1738       choice = chooser.getSelectedFile().getPath();
1739     }
1740     return choice;
1741   }
1742
1743   /**
1744    * Validate the structure tab preferences; if invalid, set focus on this tab.
1745    * 
1746    * @param e
1747    */
1748   protected boolean validateStructure(FocusEvent e)
1749   {
1750     if (!validateStructure())
1751     {
1752       e.getComponent().requestFocusInWindow();
1753       return false;
1754     }
1755     return true;
1756   }
1757
1758   protected boolean validateStructure()
1759   {
1760     return false;
1761   }
1762
1763   /**
1764    * Initialises the Visual tabbed panel.
1765    * 
1766    * @return
1767    */
1768   private JPanel initVisualTab()
1769   {
1770     JPanel visualTab = new JPanel();
1771     visualTab.setBorder(new TitledBorder(
1772             MessageManager.getString("action.open_new_alignment")));
1773     visualTab.setLayout(null);
1774     fullScreen.setFont(LABEL_FONT);
1775     fullScreen.setHorizontalAlignment(SwingConstants.RIGHT);
1776     fullScreen.setHorizontalTextPosition(SwingConstants.LEFT);
1777     fullScreen.setText(MessageManager.getString("label.maximize_window"));
1778     quality.setEnabled(false);
1779     quality.setFont(LABEL_FONT);
1780     quality.setHorizontalAlignment(SwingConstants.RIGHT);
1781     quality.setHorizontalTextPosition(SwingConstants.LEFT);
1782     quality.setSelected(true);
1783     quality.setText(MessageManager.getString("label.quality"));
1784     conservation.setEnabled(false);
1785     conservation.setFont(LABEL_FONT);
1786     conservation.setHorizontalAlignment(SwingConstants.RIGHT);
1787     conservation.setHorizontalTextPosition(SwingConstants.LEFT);
1788     conservation.setSelected(true);
1789     conservation.setText(MessageManager.getString("label.conservation"));
1790     identity.setEnabled(false);
1791     identity.setFont(LABEL_FONT);
1792     identity.setHorizontalAlignment(SwingConstants.RIGHT);
1793     identity.setHorizontalTextPosition(SwingConstants.LEFT);
1794     identity.setSelected(true);
1795     identity.setText(MessageManager.getString("label.consensus"));
1796     showOccupancy.setFont(LABEL_FONT);
1797     showOccupancy.setEnabled(false);
1798     showOccupancy.setHorizontalAlignment(SwingConstants.RIGHT);
1799     showOccupancy.setHorizontalTextPosition(SwingConstants.LEFT);
1800     showOccupancy.setSelected(true);
1801     showOccupancy.setText(MessageManager.getString("label.occupancy"));
1802
1803     JLabel showGroupbits = new JLabel();
1804     showGroupbits.setFont(LABEL_FONT);
1805     showGroupbits.setHorizontalAlignment(SwingConstants.RIGHT);
1806     showGroupbits.setHorizontalTextPosition(SwingConstants.LEFT);
1807     showGroupbits
1808             .setText(MessageManager.getString("action.show_group") + ":");
1809     JLabel showConsensbits = new JLabel();
1810     showConsensbits.setFont(LABEL_FONT);
1811     showConsensbits.setHorizontalAlignment(SwingConstants.RIGHT);
1812     showConsensbits.setHorizontalTextPosition(SwingConstants.LEFT);
1813     showConsensbits
1814             .setText(MessageManager.getString("label.consensus") + ":");
1815     showConsensHistogram.setEnabled(false);
1816     showConsensHistogram.setFont(LABEL_FONT);
1817     showConsensHistogram.setHorizontalAlignment(SwingConstants.RIGHT);
1818     showConsensHistogram.setHorizontalTextPosition(SwingConstants.LEFT);
1819     showConsensHistogram.setSelected(true);
1820     showConsensHistogram
1821             .setText(MessageManager.getString("label.histogram"));
1822     showConsensLogo.setEnabled(false);
1823     showConsensLogo.setFont(LABEL_FONT);
1824     showConsensLogo.setHorizontalAlignment(SwingConstants.RIGHT);
1825     showConsensLogo.setHorizontalTextPosition(SwingConstants.LEFT);
1826     showConsensLogo.setSelected(true);
1827     showConsensLogo.setText(MessageManager.getString("label.logo"));
1828     showGroupConsensus.setEnabled(false);
1829     showGroupConsensus.setFont(LABEL_FONT);
1830     showGroupConsensus.setHorizontalAlignment(SwingConstants.RIGHT);
1831     showGroupConsensus.setHorizontalTextPosition(SwingConstants.LEFT);
1832     showGroupConsensus.setSelected(true);
1833     showGroupConsensus.setText(MessageManager.getString("label.consensus"));
1834     showGroupConservation.setEnabled(false);
1835     showGroupConservation.setFont(LABEL_FONT);
1836     showGroupConservation.setHorizontalAlignment(SwingConstants.RIGHT);
1837     showGroupConservation.setHorizontalTextPosition(SwingConstants.LEFT);
1838     showGroupConservation.setSelected(true);
1839     showGroupConservation
1840             .setText(MessageManager.getString("label.conservation"));
1841     showNpTooltip.setEnabled(true);
1842     showNpTooltip.setFont(LABEL_FONT);
1843     showNpTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
1844     showNpTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
1845     showNpTooltip.setSelected(true);
1846     showNpTooltip.setText(
1847             MessageManager.getString("label.non_positional_features"));
1848     showDbRefTooltip.setEnabled(true);
1849     showDbRefTooltip.setFont(LABEL_FONT);
1850     showDbRefTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
1851     showDbRefTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
1852     showDbRefTooltip.setSelected(true);
1853     showDbRefTooltip
1854             .setText(MessageManager.getString("label.database_references"));
1855     annotations.setFont(LABEL_FONT);
1856     annotations.setHorizontalAlignment(SwingConstants.RIGHT);
1857     annotations.setHorizontalTextPosition(SwingConstants.LEFT);
1858     annotations.setSelected(true);
1859     annotations.setText(MessageManager.getString("label.show_annotations"));
1860     // annotations.setBounds(new Rectangle(169, 12, 200, 23));
1861     annotations.addActionListener(new ActionListener()
1862     {
1863       @Override
1864       public void actionPerformed(ActionEvent e)
1865       {
1866         annotations_actionPerformed(e);
1867       }
1868     });
1869     identity.addActionListener(new ActionListener()
1870     {
1871       @Override
1872       public void actionPerformed(ActionEvent e)
1873       {
1874         annotations_actionPerformed(e);
1875       }
1876     });
1877     showGroupConsensus.addActionListener(new ActionListener()
1878     {
1879       @Override
1880       public void actionPerformed(ActionEvent e)
1881       {
1882         annotations_actionPerformed(e);
1883       }
1884     });
1885     showUnconserved.setFont(LABEL_FONT);
1886     showUnconserved.setHorizontalAlignment(SwingConstants.RIGHT);
1887     showUnconserved.setHorizontalTextPosition(SwingConstants.LEFT);
1888     showUnconserved.setSelected(true);
1889     showUnconserved
1890             .setText(MessageManager.getString("action.show_unconserved"));
1891     showUnconserved.addActionListener(new ActionListener()
1892     {
1893       @Override
1894       public void actionPerformed(ActionEvent e)
1895       {
1896         showunconserved_actionPerformed(e);
1897       }
1898     });
1899
1900     // TODO these are not yet added to / action from Preferences
1901     // JCheckBox shareSelections = new JCheckBox();
1902     // shareSelections.setFont(verdana11);
1903     // shareSelections.setHorizontalAlignment(SwingConstants.RIGHT);
1904     // shareSelections.setHorizontalTextPosition(SwingConstants.LEFT);
1905     // shareSelections.setSelected(true);
1906     // shareSelections.setText(MessageManager
1907     // .getString("label.share_selection_across_views"));
1908     // JCheckBox followHighlight = new JCheckBox();
1909     // followHighlight.setFont(verdana11);
1910     // followHighlight.setHorizontalAlignment(SwingConstants.RIGHT);
1911     // followHighlight.setHorizontalTextPosition(SwingConstants.LEFT);
1912     // // showUnconserved.setBounds(new Rectangle(169, 40, 200, 23));
1913     // followHighlight.setSelected(true);
1914     // followHighlight.setText(MessageManager
1915     // .getString("label.scroll_highlighted_regions"));
1916
1917     seqLimit.setFont(LABEL_FONT);
1918     seqLimit.setHorizontalAlignment(SwingConstants.RIGHT);
1919     seqLimit.setHorizontalTextPosition(SwingConstants.LEFT);
1920     seqLimit.setText(MessageManager.getString("label.full_sequence_id"));
1921     smoothFont.setFont(LABEL_FONT);
1922     smoothFont.setHorizontalAlignment(SwingConstants.RIGHT);
1923     smoothFont.setHorizontalTextPosition(SwingConstants.LEADING);
1924     smoothFont.setText(MessageManager.getString("label.smooth_font"));
1925     scaleProteinToCdna.setFont(LABEL_FONT);
1926     scaleProteinToCdna.setHorizontalAlignment(SwingConstants.RIGHT);
1927     scaleProteinToCdna.setHorizontalTextPosition(SwingConstants.LEADING);
1928     scaleProteinToCdna.setText(
1929             MessageManager.getString("label.scale_protein_to_cdna"));
1930     scaleProteinToCdna.setToolTipText(
1931             MessageManager.getString("label.scale_protein_to_cdna_tip"));
1932     JLabel gapLabel = new JLabel();
1933     gapLabel.setFont(LABEL_FONT);
1934     gapLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1935     gapLabel.setText(MessageManager.getString("label.gap_symbol") + " ");
1936     JLabel fontLabel = new JLabel();
1937     fontLabel.setFont(LABEL_FONT);
1938     fontLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1939     fontLabel.setText(MessageManager.getString("label.font"));
1940     fontSizeCB.setFont(LABEL_FONT);
1941     fontSizeCB.setBounds(new Rectangle(320, 112, 65, 23));
1942     fontStyleCB.setFont(LABEL_FONT);
1943     fontStyleCB.setBounds(new Rectangle(382, 112, 80, 23));
1944     fontNameCB.setFont(LABEL_FONT);
1945     fontNameCB.setBounds(new Rectangle(172, 112, 147, 23));
1946     gapSymbolCB.setFont(LABEL_FONT);
1947     gapSymbolCB.setBounds(new Rectangle(172, 215, 69, 23));
1948     DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
1949     dlcr.setHorizontalAlignment(DefaultListCellRenderer.CENTER);
1950     gapSymbolCB.setRenderer(dlcr);
1951
1952     startupCheckbox.setText(MessageManager.getString("action.open_file"));
1953     startupCheckbox.setFont(LABEL_FONT);
1954     startupCheckbox.setHorizontalAlignment(SwingConstants.RIGHT);
1955     startupCheckbox.setHorizontalTextPosition(SwingConstants.LEFT);
1956     startupCheckbox.setSelected(true);
1957     startupFileTextfield.setFont(LABEL_FONT);
1958     startupFileTextfield.setBounds(new Rectangle(172, 310, 330, 20));
1959     final String tooltip = JvSwingUtils.wrapTooltip(true,
1960             MessageManager.getString("label.double_click_to_browse"));
1961     startupFileTextfield.setToolTipText(tooltip);
1962     startupFileTextfield.addMouseListener(new MouseAdapter()
1963     {
1964       @Override
1965       public void mouseClicked(MouseEvent e)
1966       {
1967         if (e.getClickCount() > 1)
1968         {
1969           startupFileTextfield_mouseClicked();
1970         }
1971       }
1972     });
1973
1974     sortby.setFont(LABEL_FONT);
1975     sortby.setBounds(new Rectangle(172, 260, 155, 21));
1976     JLabel sortLabel = new JLabel();
1977     sortLabel.setFont(LABEL_FONT);
1978     sortLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1979     sortLabel.setText(MessageManager.getString("label.sort_by"));
1980     sortAnnBy.setFont(LABEL_FONT);
1981     sortAnnBy.setBounds(new Rectangle(172, 285, 110, 21));
1982     JLabel sortAnnLabel = new JLabel();
1983     sortAnnLabel.setFont(LABEL_FONT);
1984     sortAnnLabel.setHorizontalAlignment(SwingConstants.RIGHT);
1985     sortAnnLabel.setText(MessageManager.getString("label.sort_ann_by"));
1986     sortAutocalc.setFont(LABEL_FONT);
1987     sortAutocalc.setBounds(new Rectangle(290, 285, 165, 21));
1988
1989     JPanel annsettingsPanel = new JPanel();
1990     annsettingsPanel.setBounds(new Rectangle(173, 13, 320, 96));
1991     annsettingsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
1992     annsettingsPanel.setBorder(new EtchedBorder());
1993     visualTab.add(annsettingsPanel);
1994     Border jb = new EmptyBorder(1, 1, 4, 5);
1995     annotations.setBorder(jb);
1996     showOccupancy.setBorder(jb);
1997     quality.setBorder(jb);
1998     conservation.setBorder(jb);
1999     identity.setBorder(jb);
2000     showConsensbits.setBorder(jb);
2001     showGroupbits.setBorder(jb);
2002     showGroupConsensus.setBorder(jb);
2003     showGroupConservation.setBorder(jb);
2004     showConsensHistogram.setBorder(jb);
2005     showConsensLogo.setBorder(jb);
2006
2007     JPanel autoAnnotSettings = new JPanel();
2008     annsettingsPanel.add(autoAnnotSettings);
2009     autoAnnotSettings.setLayout(new GridLayout(0, 2));
2010     autoAnnotSettings.add(annotations);
2011     autoAnnotSettings.add(quality);
2012     // second row of autoannotation box
2013     autoAnnotSettings = new JPanel();
2014     annsettingsPanel.add(autoAnnotSettings);
2015
2016     autoAnnotSettings.setLayout(new GridLayout(0, 3));
2017     autoAnnotSettings.add(conservation);
2018     autoAnnotSettings.add(identity);
2019     autoAnnotSettings.add(showOccupancy);
2020     autoAnnotSettings.add(showGroupbits);
2021     autoAnnotSettings.add(showGroupConservation);
2022     autoAnnotSettings.add(showGroupConsensus);
2023     autoAnnotSettings.add(showConsensbits);
2024     autoAnnotSettings.add(showConsensHistogram);
2025     autoAnnotSettings.add(showConsensLogo);
2026
2027     JPanel tooltipSettings = new JPanel();
2028     tooltipSettings.setBorder(new TitledBorder(
2029             MessageManager.getString("label.sequence_id_tooltip")));
2030     tooltipSettings.setBounds(173, 140, 220, 62);
2031     tooltipSettings.setLayout(new GridLayout(2, 1));
2032     tooltipSettings.add(showDbRefTooltip);
2033     tooltipSettings.add(showNpTooltip);
2034     visualTab.add(tooltipSettings);
2035
2036     wrap.setFont(LABEL_FONT);
2037     wrap.setHorizontalAlignment(SwingConstants.TRAILING);
2038     wrap.setHorizontalTextPosition(SwingConstants.LEADING);
2039     wrap.setText(MessageManager.getString("label.wrap_alignment"));
2040     rightAlign.setFont(LABEL_FONT);
2041     rightAlign.setForeground(Color.black);
2042     rightAlign.setHorizontalAlignment(SwingConstants.RIGHT);
2043     rightAlign.setHorizontalTextPosition(SwingConstants.LEFT);
2044     rightAlign.setText(MessageManager.getString("label.right_align_ids"));
2045     idItalics.setFont(LABEL_FONT_ITALIC);
2046     idItalics.setHorizontalAlignment(SwingConstants.RIGHT);
2047     idItalics.setHorizontalTextPosition(SwingConstants.LEADING);
2048     idItalics.setText(
2049             MessageManager.getString("label.sequence_name_italics"));
2050     openoverv.setFont(LABEL_FONT);
2051     openoverv.setActionCommand(
2052             MessageManager.getString("label.open_overview"));
2053     openoverv.setHorizontalAlignment(SwingConstants.RIGHT);
2054     openoverv.setHorizontalTextPosition(SwingConstants.LEFT);
2055     openoverv.setText(MessageManager.getString("label.open_overview"));
2056     JPanel jPanel2 = new JPanel();
2057     jPanel2.setBounds(new Rectangle(7, 17, 158, 310));
2058     jPanel2.setLayout(new GridLayout(14, 1));
2059     jPanel2.add(fullScreen);
2060     jPanel2.add(openoverv);
2061     jPanel2.add(seqLimit);
2062     jPanel2.add(rightAlign);
2063     jPanel2.add(fontLabel);
2064     jPanel2.add(showUnconserved);
2065     jPanel2.add(idItalics);
2066     jPanel2.add(smoothFont);
2067     jPanel2.add(scaleProteinToCdna);
2068     jPanel2.add(gapLabel);
2069     jPanel2.add(wrap);
2070     jPanel2.add(sortLabel);
2071     jPanel2.add(sortAnnLabel);
2072     jPanel2.add(startupCheckbox);
2073     visualTab.add(jPanel2);
2074     visualTab.add(startupFileTextfield);
2075     visualTab.add(sortby);
2076     visualTab.add(sortAnnBy);
2077     visualTab.add(sortAutocalc);
2078     visualTab.add(gapSymbolCB);
2079     visualTab.add(fontNameCB);
2080     visualTab.add(fontSizeCB);
2081     visualTab.add(fontStyleCB);
2082     return visualTab;
2083   }
2084
2085   /**
2086    * Load the saved Backups options EXCEPT "Enabled" and "Scheme"
2087    */
2088
2089   protected void loadLastSavedBackupsOptions()
2090   {
2091     BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry
2092             .getSavedBackupEntry();
2093     enableBackupFiles
2094             .setSelected(Cache.getDefault(BackupFiles.ENABLED, true));
2095
2096     BackupFilesPresetEntry backupfilesCustomEntry = BackupFilesPresetEntry
2097             .createBackupFilesPresetEntry(Cache
2098                     .getDefault(BackupFilesPresetEntry.CUSTOMCONFIG, null));
2099     if (backupfilesCustomEntry == null)
2100     {
2101       backupfilesCustomEntry = BackupFilesPresetEntry.backupfilesPresetEntriesValues
2102               .get(BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT);
2103     }
2104     BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
2105             BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM,
2106             backupfilesCustomEntry);
2107
2108     setComboIntStringKey(backupfilesPresetsCombo,
2109             Cache.getDefault(BackupFiles.NS + "_PRESET",
2110                     BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT));
2111
2112     backupsSetOptions(savedPreset);
2113
2114     backupsOptionsSetEnabled();
2115     updateBackupFilesExampleLabel();
2116   }
2117
2118   private boolean warnAboutSuffixReverseChange()
2119   {
2120     BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
2121             .getSavedBackupEntry();
2122     boolean savedSuffixReverse = bfpe.reverse;
2123     int savedSuffixDigits = bfpe.digits;
2124     String savedSuffixTemplate = bfpe.suffix;
2125
2126     boolean nowSuffixReverse = suffixReverse.isSelected();
2127     int nowSuffixDigits = getSpinnerInt(suffixDigitsSpinner, 3);
2128     String nowSuffixTemplate = suffixTemplate.getText();
2129     return nowSuffixReverse != savedSuffixReverse
2130             && nowSuffixDigits == savedSuffixDigits
2131             && nowSuffixTemplate != null
2132             && nowSuffixTemplate.equals(savedSuffixTemplate);
2133   }
2134
2135   /**
2136    * Initialises the Backups tabbed panel.
2137    * 
2138    * @return
2139    */
2140   private JPanel initBackupsTab()
2141   {
2142     JPanel backupsTab = new JPanel();
2143     backupsTab.setBorder(new TitledBorder(
2144             MessageManager.getString("label.backup_files")));
2145     backupsTab.setLayout(new GridBagLayout());
2146
2147     GridBagConstraints gbc = new GridBagConstraints();
2148     gbc.weightx = 0.0;
2149     gbc.weighty = 0.0;
2150     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
2151     gbc.fill = GridBagConstraints.NONE;
2152
2153     initBackupsTabPresetsPanel();
2154     initBackupsTabSuffixPanel();
2155     initBackupsTabKeepFilesPanel();
2156     initBackupsTabFilenameExamplesPanel();
2157
2158     enableBackupFiles.setFont(LABEL_FONT_BOLD);
2159     enableBackupFiles
2160             .setText(MessageManager.getString("label.enable_backupfiles"));
2161     enableBackupFiles.addActionListener(new ActionListener()
2162     {
2163       @Override
2164       public void actionPerformed(ActionEvent e)
2165       {
2166         // enable other options only when the first is checked
2167         backupsOptionsSetEnabled();
2168       }
2169     });
2170
2171     // enable checkbox 1 col
2172     gbc.gridwidth = 1;
2173     gbc.gridheight = 1;
2174     gbc.gridx = 0;
2175     gbc.gridy = 0; // row 0
2176     backupsTab.add(enableBackupFiles, gbc);
2177
2178     // summary of scheme box (over two rows)
2179     gbc.gridx = 1;
2180     gbc.weightx = 0.0;
2181     gbc.gridheight = 2;
2182     gbc.anchor = GridBagConstraints.FIRST_LINE_END;
2183     gbc.fill = GridBagConstraints.BOTH;
2184     backupsTab.add(exampleFilesPanel, gbc);
2185     gbc.gridheight = 1;
2186     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
2187     gbc.fill = GridBagConstraints.NONE;
2188
2189     // fill empty space on right
2190     gbc.gridx++;
2191     gbc.weightx = 1.0;
2192     backupsTab.add(new JPanel(), gbc);
2193
2194     // schemes box
2195     gbc.weightx = 0.0;
2196     gbc.gridx = 0;
2197     gbc.gridy++; // row 1
2198     backupsTab.add(presetsPanel, gbc);
2199
2200     // now using whole row
2201     gbc.gridwidth = 2;
2202     gbc.gridheight = 1;
2203     // keep files box
2204     gbc.gridx = 0;
2205     gbc.gridy++; // row 2
2206     backupsTab.add(keepfilesPanel, gbc);
2207
2208     // filename strategy box
2209     gbc.gridy++; // row 3
2210     backupsTab.add(suffixPanel, gbc);
2211
2212     // fill empty space
2213     gbc.gridy++; // row 4
2214     gbc.weighty = 1.0;
2215     backupsTab.add(new JPanel(), gbc);
2216
2217     backupsOptionsSetEnabled();
2218     return backupsTab;
2219   }
2220
2221   private JPanel initBackupsTabPresetsPanel()
2222   {
2223
2224     String title = MessageManager.getString("label.schemes");
2225
2226     presetsPanel.setLayout(new GridBagLayout());
2227
2228     GridBagConstraints gbc = new GridBagConstraints();
2229     gbc.weightx = 0.0;
2230     gbc.weighty = 0.0;
2231     gbc.anchor = GridBagConstraints.BASELINE_LEADING;
2232     gbc.fill = GridBagConstraints.NONE;
2233     gbc.gridwidth = 1;
2234     gbc.gridheight = 1;
2235
2236     // "Scheme: "
2237     gbc.gridx = 0;
2238     gbc.gridy = 0;
2239
2240     presetsComboLabel = new JLabel(title + ":");
2241     presetsPanel.add(presetsComboLabel, gbc);
2242
2243     List<Object> entries = Arrays.asList(
2244             (Object[]) BackupFilesPresetEntry.backupfilesPresetEntries);
2245     List<String> tooltips = Arrays.asList(
2246             BackupFilesPresetEntry.backupfilesPresetEntryDescriptions);
2247     backupfilesPresetsCombo = JvSwingUtils.buildComboWithTooltips(entries,
2248             tooltips);
2249     /*
2250     for (int i = 0; i < BackupFilesPresetEntry.backupfilesPresetEntries.length; i++)
2251     {
2252       backupfilesPresetsCombo
2253               .addItem(BackupFilesPresetEntry.backupfilesPresetEntries[i]);
2254     }
2255     */
2256
2257     backupfilesPresetsCombo.addActionListener(new ActionListener()
2258     {
2259       @Override
2260       public void actionPerformed(ActionEvent e)
2261       {
2262         int key = getComboIntStringKey(backupfilesPresetsCombo);
2263         if (!customiseCheckbox.isSelected())
2264         {
2265           backupfilesPresetsComboLastSelected = key;
2266         }
2267         if (key == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
2268         {
2269           if (customiseCheckbox.isSelected())
2270           {
2271             // got here by clicking on customiseCheckbox so don't change the
2272             // values
2273             backupfilesCustomOptionsSetEnabled();
2274           }
2275           else
2276           {
2277             backupsTabUpdatePresets();
2278             backupfilesCustomOptionsSetEnabled();
2279           }
2280         }
2281         else
2282         {
2283           customiseCheckbox.setSelected(false);
2284           backupsTabUpdatePresets();
2285           backupfilesCustomOptionsSetEnabled();
2286         }
2287       }
2288     });
2289
2290     // dropdown list of preset schemes
2291     gbc.gridx = 1;
2292     presetsPanel.add(backupfilesPresetsCombo, gbc);
2293
2294     revertButton.setText(MessageManager.getString("label.cancel_changes"));
2295     revertButton.setToolTipText(
2296             MessageManager.getString("label.cancel_changes_description"));
2297     revertButton.addActionListener(new ActionListener()
2298     {
2299       @Override
2300       public void actionPerformed(ActionEvent e)
2301       {
2302         backupsSetOptions(
2303                 BackupFilesPresetEntry.backupfilesPresetEntriesValues.get(
2304                         BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM));
2305         backupfilesCustomOptionsSetEnabled();
2306       }
2307
2308     });
2309     revertButton.setFont(LABEL_FONT);
2310
2311     customiseCheckbox.setFont(LABEL_FONT);
2312     customiseCheckbox.setText(MessageManager.getString("label.customise"));
2313     customiseCheckbox.addActionListener(new ActionListener()
2314     {
2315       @Override
2316       public void actionPerformed(ActionEvent e)
2317       {
2318         int currently = getComboIntStringKey(backupfilesPresetsCombo);
2319         if (customiseCheckbox.isSelected())
2320         {
2321           backupfilesPresetsComboLastSelected = currently;
2322           setComboIntStringKey(backupfilesPresetsCombo,
2323                   BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
2324         }
2325         else
2326         {
2327           setComboIntStringKey(backupfilesPresetsCombo,
2328                   backupfilesPresetsComboLastSelected);
2329
2330         }
2331         backupfilesCustomOptionsSetEnabled();
2332       }
2333     });
2334     customiseCheckbox.setToolTipText(
2335             MessageManager.getString("label.customise_description"));
2336
2337     // customise checkbox
2338     gbc.gridx = 0;
2339     gbc.gridy++;
2340     presetsPanel.add(customiseCheckbox, gbc);
2341
2342     // "Cancel changes" button (aligned with combo box above)
2343     gbc.gridx = 1;
2344     presetsPanel.add(revertButton, gbc);
2345
2346     return presetsPanel;
2347   }
2348
2349   private JPanel initBackupsTabFilenameExamplesPanel()
2350   {
2351     String title = MessageManager.getString("label.scheme_examples");
2352     TitledBorder tb = new TitledBorder(title);
2353     exampleFilesPanel.setBorder(tb);
2354     exampleFilesPanel.setLayout(new GridBagLayout());
2355
2356     backupfilesExampleLabel.setEditable(false);
2357     backupfilesExampleLabel
2358             .setBackground(exampleFilesPanel.getBackground());
2359
2360     updateBackupFilesExampleLabel();
2361
2362     GridBagConstraints gbc = new GridBagConstraints();
2363     gbc.weightx = 1.0;
2364     gbc.weighty = 1.0;
2365     gbc.fill = GridBagConstraints.NONE;
2366     gbc.anchor = GridBagConstraints.FIRST_LINE_START;
2367
2368     exampleFilesPanel.add(backupfilesExampleLabel, gbc);
2369     return exampleFilesPanel;
2370   }
2371
2372   private void backupsTabUpdatePresets()
2373   {
2374     IntKeyStringValueEntry entry = (IntKeyStringValueEntry) backupfilesPresetsCombo
2375             .getSelectedItem();
2376     int key = entry.k;
2377     String value = entry.v;
2378
2379     if (BackupFilesPresetEntry.backupfilesPresetEntriesValues
2380             .containsKey(key))
2381     {
2382       backupsSetOptions(
2383               BackupFilesPresetEntry.backupfilesPresetEntriesValues
2384                       .get(key));
2385     }
2386     else
2387     {
2388       Cache.log.error(
2389               "Preset '" + value + "' [key:" + key + "] not implemented");
2390     }
2391
2392     // Custom options will now be enabled when the customiseCheckbox is checked
2393     // (performed above)
2394     // backupfilesCustomOptionsSetEnabled();
2395     updateBackupFilesExampleLabel();
2396   }
2397
2398   protected int getComboIntStringKey(
2399           JComboBox<Object> backupfilesPresetsCombo2)
2400   {
2401     IntKeyStringValueEntry e;
2402     try
2403     {
2404       e = (IntKeyStringValueEntry) backupfilesPresetsCombo2
2405               .getSelectedItem();
2406     } catch (Exception ex)
2407     {
2408       Cache.log.error(
2409               "Problem casting Combo entry to IntKeyStringValueEntry.");
2410       e = null;
2411     }
2412     return e != null ? e.k : 0;
2413   }
2414
2415   protected void setComboIntStringKey(
2416           JComboBox<Object> backupfilesPresetsCombo2, int key)
2417   {
2418     for (int i = 0; i < backupfilesPresetsCombo2.getItemCount(); i++)
2419     {
2420       IntKeyStringValueEntry e;
2421       try
2422       {
2423         e = (IntKeyStringValueEntry) backupfilesPresetsCombo2.getItemAt(i);
2424       } catch (Exception ex)
2425       {
2426         Cache.log.error(
2427                 "Problem casting Combo entry to IntKeyStringValueEntry. Skipping item. ");
2428         continue;
2429       }
2430       if (e.k == key)
2431       {
2432         backupfilesPresetsCombo2.setSelectedIndex(i);
2433         break;
2434       }
2435     }
2436     // backupsTabUpdatePresets();
2437   }
2438
2439   private JPanel initBackupsTabSuffixPanel()
2440   {
2441     suffixPanel.setBorder(new TitledBorder(
2442             MessageManager.getString("label.backup_filename_strategy")));
2443     suffixPanel.setLayout(new GridBagLayout());
2444
2445     suffixTemplateLabel
2446             .setText(MessageManager.getString("label.append_to_filename"));
2447     suffixTemplateLabel.setHorizontalAlignment(SwingConstants.LEFT);
2448     suffixTemplateLabel.setFont(LABEL_FONT);
2449
2450     final String tooltip = JvSwingUtils.wrapTooltip(true,
2451             MessageManager.getString("label.append_to_filename_tooltip"));
2452     suffixTemplate.setToolTipText(tooltip);
2453     suffixTemplate.addActionListener(new ActionListener()
2454     {
2455       @Override
2456       public void actionPerformed(ActionEvent e)
2457       {
2458         updateBackupFilesExampleLabel();
2459         backupfilesCustomOptionsSetEnabled();
2460         backupfilesRevertButtonSetEnabled(true);
2461       }
2462
2463     });
2464     suffixTemplate.addKeyListener(new KeyListener()
2465     {
2466       @Override
2467       public void keyReleased(KeyEvent e)
2468       {
2469         updateBackupFilesExampleLabel();
2470         backupfilesCustomOptionsSetEnabled();
2471         backupfilesRevertButtonSetEnabled(true);
2472       }
2473
2474       @Override
2475       public void keyPressed(KeyEvent e)
2476       {
2477       }
2478
2479       // disable use of ':' or '/' or '\'
2480       @Override
2481       public void keyTyped(KeyEvent e)
2482       {
2483         char c = e.getKeyChar();
2484         if (c == ':' || c == '/' || c == '\\')
2485         {
2486           // don't process ':' or '/' or '\'
2487           e.consume();
2488         }
2489       }
2490
2491     });
2492
2493     // digits spinner
2494     suffixDigitsLabel
2495             .setText(MessageManager.getString("label.index_digits"));
2496     suffixDigitsLabel.setHorizontalAlignment(SwingConstants.LEFT);
2497     suffixDigitsLabel.setFont(LABEL_FONT);
2498     ChangeListener c = new ChangeListener()
2499     {
2500       @Override
2501       public void stateChanged(ChangeEvent e)
2502       {
2503         backupfilesRevertButtonSetEnabled(true);
2504         updateBackupFilesExampleLabel();
2505       }
2506
2507     };
2508     setIntegerSpinner(suffixDigitsSpinner, BackupFilesPresetEntry.DIGITSMIN,
2509             BackupFilesPresetEntry.DIGITSMAX, 3, c);
2510
2511     suffixReverse.setLabels(MessageManager.getString("label.reverse_roll"),
2512             MessageManager.getString("label.increment_index"));
2513     suffixReverse.addActionListener(new ActionListener()
2514     {
2515       @Override
2516       public void actionPerformed(ActionEvent e)
2517       {
2518         boolean okay = true;
2519         if (warnAboutSuffixReverseChange())
2520         {
2521           // Warning popup
2522           okay = confirmSuffixReverseChange();
2523         }
2524         if (okay)
2525         {
2526           backupfilesRevertButtonSetEnabled(true);
2527           updateBackupFilesExampleLabel();
2528         }
2529         else
2530         {
2531           boolean savedSuffixReverse = BackupFilesPresetEntry
2532                   .getSavedBackupEntry().reverse;
2533           suffixReverse.setSelected(savedSuffixReverse);
2534         }
2535       }
2536     });
2537
2538     GridBagConstraints sgbc = new GridBagConstraints();
2539
2540     // first row (template text box)
2541     sgbc.anchor = GridBagConstraints.WEST;
2542     sgbc.gridx = 0;
2543     sgbc.gridy = 0;
2544     sgbc.gridwidth = 1;
2545     sgbc.gridheight = 1;
2546     sgbc.weightx = 1.0;
2547     sgbc.weighty = 0.0;
2548     sgbc.fill = GridBagConstraints.NONE;
2549     suffixPanel.add(suffixTemplateLabel, sgbc);
2550
2551     sgbc.gridx = 1;
2552     sgbc.fill = GridBagConstraints.HORIZONTAL;
2553     suffixPanel.add(suffixTemplate, sgbc);
2554
2555     // second row (number of digits spinner)
2556     sgbc.gridy = 1;
2557
2558     sgbc.gridx = 0;
2559     sgbc.fill = GridBagConstraints.NONE;
2560     suffixPanel.add(suffixDigitsLabel, sgbc);
2561
2562     sgbc.gridx = 1;
2563     sgbc.fill = GridBagConstraints.HORIZONTAL;
2564     suffixPanel.add(suffixDigitsSpinner, sgbc);
2565
2566     // third row (forward order radio selection)
2567     sgbc.gridx = 0;
2568     sgbc.gridy = 2;
2569     sgbc.gridwidth = GridBagConstraints.REMAINDER;
2570     sgbc.fill = GridBagConstraints.HORIZONTAL;
2571     suffixPanel.add(suffixReverse.getFalseButton(), sgbc);
2572
2573     // fourth row (reverse order radio selection)
2574     sgbc.gridy = 3;
2575     suffixPanel.add(suffixReverse.getTrueButton(), sgbc);
2576     return suffixPanel;
2577   }
2578
2579   private boolean confirmSuffixReverseChange()
2580   {
2581     boolean ret = false;
2582     String warningMessage = MessageManager
2583             .getString("label.warning_confirm_change_reverse");
2584     int confirm = JvOptionPane.showConfirmDialog(Desktop.desktop,
2585             warningMessage,
2586             MessageManager.getString("label.change_increment_decrement"),
2587             JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE);
2588
2589     ret = (confirm == JvOptionPane.YES_OPTION);
2590     return ret;
2591   }
2592
2593   private JPanel initBackupsTabKeepFilesPanel()
2594   {
2595     keepfilesPanel.setBorder(
2596             new TitledBorder(MessageManager.getString("label.keep_files")));
2597     keepfilesPanel.setLayout(new GridBagLayout());
2598
2599     backupfilesKeepAll.setLabels(
2600             MessageManager.getString("label.keep_all_backup_files"),
2601             MessageManager.getString(
2602                     "label.keep_only_this_number_of_backup_files"));
2603     backupfilesKeepAll.addTrueActionListener(new ActionListener()
2604     {
2605       @Override
2606       public void actionPerformed(ActionEvent e)
2607       {
2608         backupfilesRevertButtonSetEnabled(true);
2609         updateBackupFilesExampleLabel();
2610       }
2611     });
2612     backupfilesKeepAll.addActionListener(new ActionListener()
2613     {
2614       @Override
2615       public void actionPerformed(ActionEvent e)
2616       {
2617         backupfilesRevertButtonSetEnabled(true);
2618         keepRollMaxOptionsEnabled();
2619         updateBackupFilesExampleLabel();
2620       }
2621     });
2622
2623     ChangeListener c = new ChangeListener()
2624     {
2625       @Override
2626       public void stateChanged(ChangeEvent e)
2627       {
2628         backupfilesRevertButtonSetEnabled(true);
2629         updateBackupFilesExampleLabel();
2630       }
2631
2632     };
2633     setIntegerSpinner(backupfilesRollMaxSpinner,
2634             BackupFilesPresetEntry.ROLLMAXMIN,
2635             BackupFilesPresetEntry.ROLLMAXMAX, 4, true, c);
2636
2637     backupfilesConfirmDelete.setLabels(
2638             MessageManager.getString("label.always_ask"),
2639             MessageManager.getString("label.auto_delete"));
2640     backupfilesConfirmDelete.addActionListener(new ActionListener()
2641     {
2642       @Override
2643       public void actionPerformed(ActionEvent e)
2644       {
2645         backupfilesRevertButtonSetEnabled(true);
2646       }
2647     });
2648     // update the enabled section
2649     keepRollMaxOptionsEnabled();
2650
2651     GridBagConstraints kgbc = new GridBagConstraints();
2652
2653     // first row (template text box)
2654     kgbc.anchor = GridBagConstraints.WEST;
2655     kgbc.gridx = 0;
2656     kgbc.gridy = 0;
2657     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2658     kgbc.gridheight = 1;
2659     kgbc.weightx = 1.0;
2660     kgbc.weighty = 0.0;
2661     kgbc.fill = GridBagConstraints.HORIZONTAL;
2662     keepfilesPanel.add(backupfilesKeepAll.getTrueButton(), kgbc);
2663
2664     // second row
2665     kgbc.gridy = 1;
2666
2667     kgbc.gridx = 0;
2668     kgbc.gridwidth = GridBagConstraints.RELATIVE;
2669     keepfilesPanel.add(backupfilesKeepAll.getFalseButton(), kgbc);
2670
2671     kgbc.gridx = 1;
2672     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2673     keepfilesPanel.add(backupfilesRollMaxSpinner, kgbc);
2674
2675     // third row (indented)
2676     kgbc.gridy = 2;
2677     kgbc.insets = new Insets(0, 20, 0, 0);
2678
2679     kgbc.gridx = 0;
2680     kgbc.gridwidth = GridBagConstraints.REMAINDER;
2681     kgbc.fill = GridBagConstraints.HORIZONTAL;
2682     kgbc.weightx = 1.0;
2683
2684     JPanel jp = new JPanel();
2685     jp.setLayout(new FlowLayout());
2686     oldBackupFilesLabel.setText(
2687             MessageManager.getString("label.autodelete_old_backup_files"));
2688     oldBackupFilesLabel.setFont(LABEL_FONT);
2689     oldBackupFilesLabel.setHorizontalAlignment(SwingConstants.LEFT);
2690     jp.add(oldBackupFilesLabel);
2691     jp.add(backupfilesConfirmDelete.getTrueButton());
2692     jp.add(backupfilesConfirmDelete.getFalseButton());
2693     keepfilesPanel.add(jp, kgbc);
2694
2695     return keepfilesPanel;
2696   }
2697
2698   protected void updateBackupFilesExampleLabel()
2699   {
2700     int exampleindex = 12;
2701     String base = MessageManager.getString("label.filename") + ".fa";
2702     if (base == null || base.length() == 0)
2703     {
2704       base = "file_name.fa";
2705     }
2706
2707     boolean reverse = suffixReverse.isSelected();
2708     boolean keepAll = backupfilesKeepAll.isSelected();
2709     int rollMax = 4;
2710     String suffix = suffixTemplate.getText();
2711     int digits = 3;
2712
2713     backupfilesExampleLabel.setFont(LABEL_FONT_ITALIC);
2714     if (suffix == null || suffix.length() == 0)
2715     {
2716       backupfilesExampleLabel
2717               .setText(MessageManager.getString("label.no_backup_files"));
2718       backupfilesExampleLabel.setFont(LABEL_FONT_BOLD);
2719       return;
2720     }
2721
2722     rollMax = getSpinnerInt(backupfilesRollMaxSpinner, 4);
2723     rollMax = rollMax < 1 ? 1 : rollMax;
2724
2725     if (suffix.indexOf(BackupFiles.NUM_PLACEHOLDER) == -1)
2726     {
2727       rollMax = 1;
2728     }
2729
2730     digits = getSpinnerInt(suffixDigitsSpinner, 3);
2731     digits = digits < 1 ? 1 : digits;
2732
2733     int lowersurround = 2;
2734     int uppersurround = 0;
2735     StringBuilder exampleSB = new StringBuilder();
2736     boolean firstLine = true;
2737     int lineNumber = 0;
2738     if (reverse)
2739     {
2740
2741       int min = 1;
2742       int max = keepAll ? exampleindex : rollMax;
2743       for (int index = min; index <= max; index++)
2744       {
2745         if (index == min + lowersurround && index < max - uppersurround - 1)
2746         {
2747           exampleSB.append("\n...");
2748           lineNumber++;
2749         }
2750         else if (index > min + lowersurround && index < max - uppersurround)
2751         {
2752           // nothing
2753         }
2754         else
2755         {
2756           if (firstLine)
2757           {
2758             firstLine = false;
2759           }
2760           else
2761           {
2762             exampleSB.append("\n");
2763             lineNumber++;
2764           }
2765           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
2766                   base, suffix, digits));
2767           if (min == max)
2768           {
2769             // no extra text needed
2770           }
2771           else if (index == min)
2772           {
2773             String newest = MessageManager.getString("label.braced_newest");
2774             if (newest != null && newest.length() > 0)
2775             {
2776               exampleSB.append(" " + newest);
2777             }
2778           }
2779           else if (index == max)
2780           {
2781             String oldest = MessageManager.getString("label.braced_oldest");
2782             if (oldest != null && oldest.length() > 0)
2783             {
2784               exampleSB.append(" " + oldest);
2785             }
2786           }
2787         }
2788       }
2789     }
2790     else
2791     {
2792
2793       int min = (keepAll || exampleindex - rollMax < 0) ? 1
2794               : exampleindex - rollMax + 1;
2795       int max = exampleindex;
2796
2797       for (int index = min; index <= max; index++)
2798       {
2799
2800         if (index == min + lowersurround && index < max - uppersurround - 1)
2801         {
2802           exampleSB.append("\n...");
2803           lineNumber++;
2804         }
2805         else if (index > min + lowersurround && index < max - uppersurround)
2806         {
2807           // nothing
2808         }
2809         else
2810         {
2811           if (firstLine)
2812           {
2813             firstLine = false;
2814           }
2815           else
2816           {
2817             exampleSB.append("\n");
2818             lineNumber++;
2819           }
2820           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
2821                   base, suffix, digits));
2822           if (min == max)
2823           {
2824             // no extra text needed
2825           }
2826           else if (index == min)
2827           {
2828             String oldest = MessageManager.getString("label.braced_oldest");
2829             if (oldest != null && oldest.length() > 0)
2830             {
2831               exampleSB.append(" " + oldest);
2832             }
2833           }
2834           else if (index == max)
2835           {
2836             String newest = MessageManager.getString("label.braced_newest");
2837             if (newest != null && newest.length() > 0)
2838             {
2839               exampleSB.append(" " + newest);
2840             }
2841           }
2842         }
2843       }
2844
2845     }
2846
2847     // add some extra empty lines to pad out the example files box. ugh, please
2848     // tell
2849     // me how to do this better
2850     int remainingLines = lowersurround + uppersurround + 1 - lineNumber;
2851     if (remainingLines > 0)
2852     {
2853       for (int i = 0; i < remainingLines; i++)
2854       {
2855         exampleSB.append("\n ");
2856         lineNumber++;
2857       }
2858     }
2859
2860     backupfilesExampleLabel.setText(exampleSB.toString());
2861   }
2862
2863   protected void setIntegerSpinner(JSpinner s, int min, int max, int def,
2864           boolean useExistingVal, ChangeListener c)
2865   {
2866     int i = def;
2867     if (useExistingVal)
2868     {
2869       try
2870       {
2871         i = ((Integer) s.getValue()).intValue();
2872       } catch (Exception e)
2873       {
2874         Cache.log.error(
2875                 "Exception casting the initial value of s.getValue()");
2876       }
2877     }
2878
2879     setIntegerSpinner(s, min, max, i, c);
2880   }
2881
2882   protected void setIntegerSpinner(JSpinner s, int min, int max, int def,
2883           ChangeListener c)
2884   {
2885     // integer spinner for number of digits
2886     if (def > max)
2887     {
2888       max = def;
2889     }
2890     if (def < min)
2891     {
2892       def = min;
2893     }
2894     SpinnerModel sModel = new SpinnerNumberModel(def, min, max, 1);
2895     s.setModel(sModel);
2896
2897     s.addChangeListener(c);
2898
2899   }
2900
2901   protected static int getSpinnerInt(JSpinner s, int def)
2902   {
2903     int i = def;
2904     try
2905     {
2906       s.commitEdit();
2907       i = (Integer) s.getValue();
2908     } catch (Exception e)
2909     {
2910       Cache.log.error("Failed casting (Integer) JSpinner s.getValue()");
2911     }
2912     return i;
2913   }
2914
2915   private void keepRollMaxOptionsEnabled()
2916   {
2917     boolean enabled = backupfilesKeepAll.isEnabled()
2918             && !backupfilesKeepAll.isSelected();
2919     oldBackupFilesLabel.setEnabled(enabled);
2920     backupfilesRollMaxSpinner.setEnabled(enabled);
2921     backupfilesConfirmDelete.setEnabled(enabled);
2922   }
2923
2924   private void backupfilesKeepAllSetEnabled(boolean tryEnabled)
2925   {
2926     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2927             && customiseCheckbox.isSelected() && suffixTemplate.getText()
2928                     .indexOf(BackupFiles.NUM_PLACEHOLDER) > -1;
2929     keepfilesPanel.setEnabled(enabled);
2930     backupfilesKeepAll.setEnabled(enabled);
2931     oldBackupFilesLabel.setEnabled(enabled);
2932     keepRollMaxOptionsEnabled();
2933   }
2934
2935   private void backupfilesSuffixTemplateDigitsSetEnabled()
2936   {
2937     boolean enabled = suffixTemplate.isEnabled() && suffixTemplate.getText()
2938             .indexOf(BackupFiles.NUM_PLACEHOLDER) > -1;
2939     suffixDigitsLabel.setEnabled(enabled);
2940     suffixDigitsSpinner.setEnabled(enabled);
2941     suffixReverse.setEnabled(enabled);
2942   }
2943
2944   private void backupfilesSuffixTemplateSetEnabled(boolean tryEnabled)
2945   {
2946     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2947             && customiseCheckbox.isSelected();
2948     suffixPanel.setEnabled(enabled);
2949     suffixTemplateLabel.setEnabled(enabled);
2950     suffixTemplate.setEnabled(enabled);
2951     backupfilesSuffixTemplateDigitsSetEnabled();
2952   }
2953
2954   private void backupfilesRevertButtonSetEnabled(boolean tryEnabled)
2955   {
2956     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
2957             && customiseCheckbox.isSelected() && backupfilesCustomChanged();
2958     revertButton.setEnabled(enabled);
2959   }
2960
2961   private boolean backupfilesCustomChanged()
2962   {
2963     BackupFilesPresetEntry custom = BackupFilesPresetEntry.backupfilesPresetEntriesValues
2964             .get(BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
2965     BackupFilesPresetEntry current = getBackupfilesCurrentEntry();
2966     return !custom.equals(current);
2967   }
2968
2969   protected BackupFilesPresetEntry getBackupfilesCurrentEntry()
2970   {
2971     String suffix = suffixTemplate.getText();
2972     int digits = getSpinnerInt(suffixDigitsSpinner, 3);
2973     boolean reverse = suffixReverse.isSelected();
2974     boolean keepAll = backupfilesKeepAll.isSelected();
2975     int rollMax = getSpinnerInt(backupfilesRollMaxSpinner, 3);
2976     boolean confirmDelete = backupfilesConfirmDelete.isSelected();
2977
2978     BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits,
2979             reverse, keepAll, rollMax, confirmDelete);
2980
2981     return bfpe;
2982   }
2983
2984   protected void backupfilesCustomOptionsSetEnabled()
2985   {
2986     boolean enabled = customiseCheckbox.isSelected();
2987
2988     backupfilesRevertButtonSetEnabled(enabled);
2989     backupfilesSuffixTemplateSetEnabled(enabled);
2990     backupfilesKeepAllSetEnabled(enabled);
2991   }
2992
2993   private void backupfilesSummarySetEnabled()
2994   {
2995     boolean enabled = enableBackupFiles.isSelected();
2996     backupfilesExampleLabel.setEnabled(enabled);
2997     exampleFilesPanel.setEnabled(enabled);
2998   }
2999
3000   private void backupfilesPresetsSetEnabled()
3001   {
3002     boolean enabled = enableBackupFiles.isSelected();
3003     presetsPanel.setEnabled(enabled);
3004     presetsComboLabel.setEnabled(enabled);
3005     backupfilesPresetsCombo.setEnabled(enabled);
3006     customiseCheckbox.setEnabled(enabled);
3007     revertButton.setEnabled(enabled);
3008   }
3009
3010   protected void backupsOptionsSetEnabled()
3011   {
3012     backupfilesPresetsSetEnabled();
3013     backupfilesSummarySetEnabled();
3014     backupfilesCustomOptionsSetEnabled();
3015   }
3016
3017   protected void backupsSetOptions(String suffix, int digits,
3018           boolean reverse, boolean keepAll, int rollMax,
3019           boolean confirmDelete)
3020   {
3021     suffixTemplate.setText(suffix);
3022     suffixDigitsSpinner.setValue(digits);
3023     suffixReverse.setSelected(reverse);
3024     backupfilesKeepAll.setSelected(keepAll);
3025     backupfilesRollMaxSpinner.setValue(rollMax);
3026     backupfilesConfirmDelete.setSelected(confirmDelete);
3027   }
3028
3029   protected void backupsSetOptions(BackupFilesPresetEntry p)
3030   {
3031     backupsSetOptions(p.suffix, p.digits, p.reverse, p.keepAll, p.rollMax,
3032             p.confirmDelete);
3033   }
3034
3035   protected void autoIdWidth_actionPerformed()
3036   {
3037     // TODO Auto-generated method stub
3038
3039   }
3040
3041   protected void userIdWidth_actionPerformed()
3042   {
3043     // TODO Auto-generated method stub
3044
3045   }
3046
3047   protected void maxColour_actionPerformed(JPanel panel)
3048   {
3049   }
3050
3051   protected void minColour_actionPerformed(JPanel panel)
3052   {
3053   }
3054
3055   protected void gapColour_actionPerformed(JPanel panel)
3056   {
3057   }
3058
3059   protected void hiddenColour_actionPerformed(JPanel panel)
3060   {
3061   }
3062
3063   protected void showunconserved_actionPerformed(ActionEvent e)
3064   {
3065     // TODO Auto-generated method stub
3066
3067   }
3068
3069   protected void useLegacyGaps_actionPerformed(ActionEvent e)
3070   {
3071   }
3072
3073   protected void resetOvDefaults_actionPerformed(ActionEvent e)
3074   {
3075   }
3076
3077   /**
3078    * DOCUMENT ME!
3079    * 
3080    * @param e
3081    *          DOCUMENT ME!
3082    */
3083   public void ok_actionPerformed(ActionEvent e)
3084   {
3085   }
3086
3087   /**
3088    * DOCUMENT ME!
3089    * 
3090    * @param e
3091    *          DOCUMENT ME!
3092    */
3093   public void cancel_actionPerformed(ActionEvent e)
3094   {
3095   }
3096
3097   /**
3098    * DOCUMENT ME!
3099    * 
3100    * @param e
3101    *          DOCUMENT ME!
3102    */
3103   public void annotations_actionPerformed(ActionEvent e)
3104   {
3105   }
3106
3107   /**
3108    * DOCUMENT ME!
3109    */
3110   public void startupFileTextfield_mouseClicked()
3111   {
3112   }
3113
3114   public void newLink_actionPerformed(ActionEvent e)
3115   {
3116
3117   }
3118
3119   public void editLink_actionPerformed(ActionEvent e)
3120   {
3121
3122   }
3123
3124   public void deleteLink_actionPerformed(ActionEvent e)
3125   {
3126
3127   }
3128
3129   public void defaultBrowser_mouseClicked(MouseEvent e)
3130   {
3131
3132   }
3133
3134   public void linkURLList_keyTyped(KeyEvent e)
3135   {
3136
3137   }
3138
3139   public void setProxyAuthEnabled()
3140   {
3141     boolean enabled = proxyAuth.isSelected() && proxyAuth.isEnabled();
3142     proxyAuthUsernameLabel.setEnabled(enabled);
3143     proxyAuthPasswordLabel.setEnabled(enabled);
3144     passwordNotStoredLabel.setEnabled(enabled);
3145     proxyAuthUsernameTB.setEnabled(enabled);
3146     proxyAuthPasswordPB.setEnabled(enabled);
3147   }
3148
3149   public void setCustomProxyEnabled()
3150   {
3151     boolean enabled = customProxy.isSelected();
3152     portLabel.setEnabled(enabled);
3153     serverLabel.setEnabled(enabled);
3154     portLabel2.setEnabled(enabled);
3155     serverLabel2.setEnabled(enabled);
3156     httpLabel.setEnabled(enabled);
3157     httpsLabel.setEnabled(enabled);
3158     proxyServerHttpTB.setEnabled(enabled);
3159     proxyPortHttpTB.setEnabled(enabled);
3160     proxyServerHttpsTB.setEnabled(enabled);
3161     proxyPortHttpsTB.setEnabled(enabled);
3162     proxyAuth.setEnabled(enabled);
3163     setProxyAuthEnabled();
3164   }
3165
3166   public void proxyType_actionPerformed()
3167   {
3168     setCustomProxyEnabled();
3169     proxyAuthPasswordCheckHighlight(true);
3170     applyProxyButtonEnabled(true);
3171   }
3172
3173   public void proxyAuth_actionPerformed()
3174   {
3175     setProxyAuthEnabled();
3176     proxyAuthPasswordCheckHighlight(true);
3177     applyProxyButtonEnabled(true);
3178   }
3179
3180   /**
3181    * Customer renderer for JTable: supports column of radio buttons
3182    */
3183   public class RadioButtonRenderer extends JRadioButton
3184           implements TableCellRenderer
3185   {
3186     public RadioButtonRenderer()
3187     {
3188       setHorizontalAlignment(CENTER);
3189       setToolTipText(MessageManager.getString("label.urltooltip"));
3190     }
3191
3192     @Override
3193     public Component getTableCellRendererComponent(JTable table,
3194             Object value, boolean isSelected, boolean hasFocus, int row,
3195             int column)
3196     {
3197       setSelected((boolean) value);
3198
3199       // set colours to match rest of table
3200       if (isSelected)
3201       {
3202         setBackground(table.getSelectionBackground());
3203         setForeground(table.getSelectionForeground());
3204       }
3205       else
3206       {
3207         setBackground(table.getBackground());
3208         setForeground(table.getForeground());
3209       }
3210       return this;
3211     }
3212   }
3213
3214   /**
3215    * Customer cell editor for JTable: supports column of radio buttons in
3216    * conjunction with renderer
3217    */
3218   public class RadioButtonEditor extends AbstractCellEditor
3219           implements TableCellEditor
3220   {
3221     private JRadioButton button = new JRadioButton();
3222
3223     public RadioButtonEditor()
3224     {
3225       button.setHorizontalAlignment(SwingConstants.CENTER);
3226       this.button.addActionListener(new ActionListener()
3227       {
3228         @Override
3229         public void actionPerformed(ActionEvent e)
3230         {
3231           fireEditingStopped();
3232         }
3233       });
3234     }
3235
3236     @Override
3237     public Component getTableCellEditorComponent(JTable table, Object value,
3238             boolean isSelected, int row, int column)
3239     {
3240       button.setSelected((boolean) value);
3241       return button;
3242     }
3243
3244     @Override
3245     public Object getCellEditorValue()
3246     {
3247       return button.isSelected();
3248     }
3249
3250   }
3251 }