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