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