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