2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Dimension;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.awt.event.MouseEvent;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.concurrent.CompletableFuture;
36 import javax.help.HelpSetException;
37 import javax.swing.JComboBox;
38 import javax.swing.JFileChooser;
39 import javax.swing.JInternalFrame;
40 import javax.swing.JPanel;
41 import javax.swing.ListSelectionModel;
42 import javax.swing.RowFilter;
43 import javax.swing.RowSorter;
44 import javax.swing.SortOrder;
45 import javax.swing.event.DocumentEvent;
46 import javax.swing.event.DocumentListener;
47 import javax.swing.event.ListSelectionEvent;
48 import javax.swing.event.ListSelectionListener;
49 import javax.swing.table.TableCellRenderer;
50 import javax.swing.table.TableColumn;
51 import javax.swing.table.TableModel;
52 import javax.swing.table.TableRowSorter;
54 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
55 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
56 import jalview.bin.Cache;
57 import jalview.ext.pymol.PymolManager;
58 import jalview.gui.Help.HelpId;
59 import jalview.gui.StructureViewer.ViewerType;
60 import jalview.io.BackupFiles;
61 import jalview.io.BackupFilesPresetEntry;
62 import jalview.io.FileFormatI;
63 import jalview.io.JalviewFileChooser;
64 import jalview.io.JalviewFileView;
65 import jalview.jbgui.GPreferences;
66 import jalview.jbgui.GSequenceLink;
67 import jalview.schemes.ColourSchemeI;
68 import jalview.schemes.ColourSchemes;
69 import jalview.schemes.ResidueColourScheme;
70 import jalview.urls.UrlLinkTableModel;
71 import jalview.urls.api.UrlProviderFactoryI;
72 import jalview.urls.api.UrlProviderI;
73 import jalview.urls.desktop.DesktopUrlProviderFactory;
74 import jalview.util.MessageManager;
75 import jalview.util.Platform;
76 import jalview.util.UrlConstants;
77 import jalview.ws.sifts.SiftsSettings;
86 * for merge with Jalview-JS
87 public class Preferences extends GPreferences implements ApplicationSingletonI
89 public class Preferences extends GPreferences
91 public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
93 public static final String SCALE_PROTEIN_TO_CDNA = "SCALE_PROTEIN_TO_CDNA";
95 public static final String DEFAULT_COLOUR = "DEFAULT_COLOUR";
97 public static final String DEFAULT_COLOUR_PROT = "DEFAULT_COLOUR_PROT";
99 public static final String DEFAULT_COLOUR_NUC = "DEFAULT_COLOUR_NUC";
101 public static final String ADD_TEMPFACT_ANN = "ADD_TEMPFACT_ANN";
103 public static final String ADD_SS_ANN = "ADD_SS_ANN";
105 public static final String USE_RNAVIEW = "USE_RNAVIEW";
107 public static final String STRUCT_FROM_PDB = "STRUCT_FROM_PDB";
109 public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
111 public static final String CHIMERA_PATH = "CHIMERA_PATH";
113 public static final String CHIMERAX_PATH = "CHIMERAX_PATH";
115 public static final String PYMOL_PATH = "PYMOL_PATH";
117 public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
119 public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
121 public static final String SHOW_OCCUPANCY = "SHOW_OCCUPANCY";
123 public static final String SHOW_OV_HIDDEN_AT_START = "SHOW_OV_HIDDEN_AT_START";
125 public static final String USE_LEGACY_GAP = "USE_LEGACY_GAP";
127 public static final String GAP_COLOUR = "GAP_COLOUR";
129 public static final String HIDDEN_COLOUR = "HIDDEN_COLOUR";
131 private static final int MIN_FONT_SIZE = 1;
133 private static final int MAX_FONT_SIZE = 30;
135 private String previousProxyType;
137 private static Preferences INSTANCE = null; // add "final"
140 * Holds name and link separated with | character. Sequence ID must be
141 * $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$
143 public static UrlProviderI sequenceUrlLinks;
145 public static UrlLinkTableModel dataModel;
148 * Holds name and link separated with | character. Sequence IDS and Sequences
149 * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and $SEQUENCES$
150 * or $SEQUENCES=/.possible | chars ./=$ and separation character for first and
151 * second token specified after a pipe character at end |,|. (TODO: proper
152 * escape for using | to separate ids or sequences
155 public static List<String> groupURLLinks;
158 // get links selected to be in the menu (SEQUENCE_LINKS)
159 // and links entered by the user but not selected (STORED_LINKS)
160 String inMenuString = Cache.getDefault("SEQUENCE_LINKS", "");
161 String notInMenuString = Cache.getDefault("STORED_LINKS", "");
162 String defaultUrl = Cache.getDefault("DEFAULT_URL",
163 UrlConstants.DEFAULT_LABEL);
165 // if both links lists are empty, add the DEFAULT_URL link
166 // otherwise we assume the default link is in one of the lists
167 if (inMenuString.isEmpty() && notInMenuString.isEmpty())
169 inMenuString = UrlConstants.DEFAULT_STRING;
171 UrlProviderFactoryI factory = new DesktopUrlProviderFactory(defaultUrl,
172 inMenuString, notInMenuString);
173 sequenceUrlLinks = factory.createUrlProvider();
174 dataModel = new UrlLinkTableModel(sequenceUrlLinks);
177 * TODO: reformulate groupURL encoding so two or more can be stored in the
178 * .properties file as '|' separated strings
181 groupURLLinks = new ArrayList<>();
184 JInternalFrame frame;
186 private WsPreferences wsPrefs;
188 private OptionsParam promptEachTimeOpt = new OptionsParam(
189 MessageManager.getString("label.prompt_each_time"),
192 private OptionsParam lineArtOpt = new OptionsParam(
193 MessageManager.getString("label.lineart"), "Lineart");
195 private OptionsParam textOpt = new OptionsParam(
196 MessageManager.getString("action.text"), "Text");
198 // get singleton Preferences instance
199 public static Preferences getInstance()
201 if (INSTANCE == null || INSTANCE.frame == null
202 || INSTANCE.frame.isClosed())
204 INSTANCE = new Preferences();
209 * Replace code with the following for Jalvew-JS
210 Preferences INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
211 if (INSTANCE == null || INSTANCE.frame == null
212 || INSTANCE.frame.isClosed())
214 ApplicationSingletonProvider.remove(Preferences.class);
215 INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
221 public static void openPreferences()
223 openPreferences(null, null);
226 public static void openPreferences(TabRef selectTab, String message)
228 Preferences p = getInstance();
229 if (selectTab != null)
230 p.selectTab(selectTab, message);
232 p.frame.moveToFront();
236 public void selectTab(TabRef selectTab, String message)
238 this.selectTab(selectTab);
240 this.setMessage(message);
245 * Creates a new Preferences object.
247 private Preferences()
250 frame = new JInternalFrame();
251 frame.setContentPane(this);
252 if (!Platform.isJS())
259 wsPrefs = new WsPreferences();
260 wsTab.add(wsPrefs, BorderLayout.CENTER);
262 int width = 500, height = 450;
263 if (Platform.isAMacAndNotJS())
269 Desktop.addInternalFrame(frame,
270 MessageManager.getString("label.preferences"), width, height);
271 frame.setMinimumSize(new Dimension(width, height));
274 * Set Visual tab defaults
276 seqLimit.setSelected(Cache.getDefault("SHOW_JVSUFFIX", true));
277 rightAlign.setSelected(Cache.getDefault("RIGHT_ALIGN_IDS", false));
278 fullScreen.setSelected(Cache.getDefault("SHOW_FULLSCREEN", false));
279 annotations.setSelected(Cache.getDefault("SHOW_ANNOTATIONS", true));
281 conservation.setSelected(Cache.getDefault("SHOW_CONSERVATION", true));
282 quality.setSelected(Cache.getDefault("SHOW_QUALITY", true));
283 identity.setSelected(Cache.getDefault("SHOW_IDENTITY", true));
284 openoverv.setSelected(Cache.getDefault("SHOW_OVERVIEW", false));
286 .setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
287 showOccupancy.setSelected(Cache.getDefault(SHOW_OCCUPANCY, false));
289 .setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS", false));
290 showGroupConservation.setSelected(
291 Cache.getDefault("SHOW_GROUP_CONSERVATION", false));
292 showConsensHistogram.setSelected(
293 Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
295 .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
297 .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
299 .setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP", true));
301 String[] fonts = java.awt.GraphicsEnvironment
302 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
303 for (int i = 0; i < fonts.length; i++)
305 fontNameCB.addItem(fonts[i]);
308 for (int i = MIN_FONT_SIZE; i <= MAX_FONT_SIZE; i++)
310 fontSizeCB.addItem(i + "");
313 fontStyleCB.addItem("plain");
314 fontStyleCB.addItem("bold");
315 fontStyleCB.addItem("italic");
317 fontNameCB.setSelectedItem(Cache.getDefault("FONT_NAME", "SansSerif"));
318 fontSizeCB.setSelectedItem(Cache.getDefault("FONT_SIZE", "10"));
319 fontStyleCB.setSelectedItem(
320 Cache.getDefault("FONT_STYLE", Font.PLAIN + ""));
322 smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", true));
324 .setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA, false));
326 idItalics.setSelected(Cache.getDefault("ID_ITALICS", true));
328 wrap.setSelected(Cache.getDefault("WRAP_ALIGNMENT", false));
330 gapSymbolCB.addItem("-");
331 gapSymbolCB.addItem(".");
333 gapSymbolCB.setSelectedItem(Cache.getDefault("GAP_SYMBOL", "-"));
335 sortby.addItem("No sort");
336 sortby.addItem("Id");
337 sortby.addItem("Pairwise Identity");
338 sortby.setSelectedItem(Cache.getDefault("SORT_ALIGNMENT", "No sort"));
340 sortAnnBy.addItem(SequenceAnnotationOrder.NONE.toString());
342 .addItem(SequenceAnnotationOrder.SEQUENCE_AND_LABEL.toString());
344 .addItem(SequenceAnnotationOrder.LABEL_AND_SEQUENCE.toString());
345 SequenceAnnotationOrder savedSort = SequenceAnnotationOrder
346 .valueOf(Cache.getDefault(SORT_ANNOTATIONS,
347 SequenceAnnotationOrder.NONE.name()));
348 sortAnnBy.setSelectedItem(savedSort.toString());
350 sortAutocalc.addItem("Autocalculated first");
351 sortAutocalc.addItem("Autocalculated last");
352 final boolean showAbove = Cache.getDefault(SHOW_AUTOCALC_ABOVE, true);
353 sortAutocalc.setSelectedItem(showAbove ? sortAutocalc.getItemAt(0)
354 : sortAutocalc.getItemAt(1));
356 .setSelected(Cache.getDefault("SHOW_STARTUP_FILE", true));
357 startupFileTextfield.setText(Cache.getDefault("STARTUP_FILE",
358 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
359 + "/examples/exampleFile_2_7.jvp"));
362 * Set Colours tab defaults
364 protColour.addItem(ResidueColourScheme.NONE);
365 nucColour.addItem(ResidueColourScheme.NONE);
366 for (ColourSchemeI cs : ColourSchemes.getInstance().getColourSchemes())
368 String name = cs.getSchemeName();
369 protColour.addItem(name);
370 nucColour.addItem(name);
372 String oldProp = Cache.getDefault(DEFAULT_COLOUR,
373 ResidueColourScheme.NONE);
374 String newProp = Cache.getDefault(DEFAULT_COLOUR_PROT, null);
375 protColour.setSelectedItem(newProp != null ? newProp : oldProp);
376 newProp = Cache.getDefault(DEFAULT_COLOUR_NUC, null);
377 nucColour.setSelectedItem(newProp != null ? newProp : oldProp);
378 minColour.setBackground(
379 Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
380 maxColour.setBackground(
381 Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
384 * Set overview panel defaults
386 gapColour.setBackground(Cache.getDefaultColour(GAP_COLOUR,
387 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP));
388 hiddenColour.setBackground(Cache.getDefaultColour(HIDDEN_COLOUR,
389 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN));
390 useLegacyGap.setSelected(Cache.getDefault(USE_LEGACY_GAP, false));
391 gapLabel.setEnabled(!useLegacyGap.isSelected());
392 gapColour.setEnabled(!useLegacyGap.isSelected());
394 .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, false));
397 * Set Structure tab defaults
399 final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, true);
400 structFromPdb.setSelected(structSelected);
401 addSecondaryStructure.setSelected(Cache.getDefault(ADD_SS_ANN, true));
402 addSecondaryStructure.setEnabled(structSelected);
403 addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, true));
404 addTempFactor.setEnabled(structSelected);
407 * set choice of structure viewer, and path if saved as a preference;
408 * default to Jmol (first choice) if an unexpected value is found
410 String viewerType = Cache.getDefault(STRUCTURE_DISPLAY,
411 ViewerType.JMOL.name());
412 structViewer.setSelectedItem(viewerType);
413 String viewerPath = "";
414 ViewerType type = null;
417 type = ViewerType.valueOf(viewerType);
423 viewerPath = Cache.getDefault(CHIMERA_PATH, "");
426 viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
429 viewerPath = Cache.getDefault(PYMOL_PATH, "");
432 } catch (IllegalArgumentException e)
434 Cache.log.error("Unknown structure viewer type: " + viewerType
435 + ", defaulting to Jmol");
436 type = ViewerType.JMOL;
438 structureViewerPath.setText(viewerPath);
440 structureViewerPath.addActionListener(new ActionListener()
443 public void actionPerformed(ActionEvent e)
445 if (validateViewerPath())
447 String path = structureViewerPath.getText();
449 ViewerType type = ViewerType.valueOf(viewerType);
455 Cache.setProperty(CHIMERA_PATH, path);
458 Cache.setProperty(CHIMERAX_PATH, path);
461 Cache.setProperty(PYMOL_PATH, path);
464 } catch (IllegalArgumentException x)
466 Cache.log.error("Failed to set path - unknown viewer type",x);
472 if (Cache.getDefault("MAP_WITH_SIFTS", false))
474 siftsMapping.setSelected(true);
478 nwMapping.setSelected(true);
482 .setMapWithSifts(Cache.getDefault("MAP_WITH_SIFTS", false));
485 * Set Connections tab defaults
489 linkUrlTable.setModel(dataModel);
490 final TableRowSorter<TableModel> sorter = new TableRowSorter<>(
491 linkUrlTable.getModel());
492 linkUrlTable.setRowSorter(sorter);
493 List<RowSorter.SortKey> sortKeys = new ArrayList<>();
495 UrlLinkTableModel m = (UrlLinkTableModel) linkUrlTable.getModel();
496 sortKeys.add(new RowSorter.SortKey(m.getPrimaryColumn(),
497 SortOrder.DESCENDING));
498 sortKeys.add(new RowSorter.SortKey(m.getSelectedColumn(),
499 SortOrder.DESCENDING));
501 new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING));
503 sorter.setSortKeys(sortKeys);
504 // BH 2018 setSortKeys will do the sort
508 ActionListener onReset;
509 onReset = new ActionListener()
512 public void actionPerformed(ActionEvent e)
514 filterTB.setText("");
515 sorter.setRowFilter(RowFilter.regexFilter(""));
519 doReset.addActionListener(onReset);
521 // filter to display only custom urls
522 final RowFilter<TableModel, Object> customUrlFilter = new RowFilter<TableModel, Object>()
525 public boolean include(
526 Entry<? extends TableModel, ? extends Object> entry)
528 return ((UrlLinkTableModel) entry.getModel()).isUserEntry(entry);
532 final TableRowSorter<TableModel> customSorter = new TableRowSorter<>(
533 linkUrlTable.getModel());
534 customSorter.setRowFilter(customUrlFilter);
536 ActionListener onCustomOnly;
537 onCustomOnly = new ActionListener()
540 public void actionPerformed(ActionEvent e)
542 filterTB.setText("");
543 sorter.setRowFilter(customUrlFilter);
546 userOnly.addActionListener(onCustomOnly);
548 filterTB.getDocument().addDocumentListener(new DocumentListener()
550 String caseInsensitiveFlag = "(?i)";
553 public void changedUpdate(DocumentEvent e)
555 sorter.setRowFilter(RowFilter
556 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
560 public void removeUpdate(DocumentEvent e)
562 sorter.setRowFilter(RowFilter
563 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
567 public void insertUpdate(DocumentEvent e)
569 sorter.setRowFilter(RowFilter
570 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
574 // set up list selection functionality
575 linkUrlTable.getSelectionModel()
576 .addListSelectionListener(new UrlListSelectionHandler());
578 // set up radio buttons
579 int onClickCol = ((UrlLinkTableModel) linkUrlTable.getModel())
581 String onClickName = linkUrlTable.getColumnName(onClickCol);
582 linkUrlTable.getColumn(onClickName)
583 .setCellRenderer(new RadioButtonRenderer());
584 linkUrlTable.getColumn(onClickName)
585 .setCellEditor(new RadioButtonEditor());
587 // get boolean columns and resize those to min possible
588 for (int column = 0; column < linkUrlTable.getColumnCount(); column++)
590 if (linkUrlTable.getModel().getColumnClass(column)
591 .equals(Boolean.class))
593 TableColumn tableColumn = linkUrlTable.getColumnModel()
595 int preferredWidth = tableColumn.getMinWidth();
597 TableCellRenderer cellRenderer = linkUrlTable.getCellRenderer(0,
599 Component c = linkUrlTable.prepareRenderer(cellRenderer, 0, column);
600 int cwidth = c.getPreferredSize().width
601 + linkUrlTable.getIntercellSpacing().width;
602 preferredWidth = Math.max(preferredWidth, cwidth);
604 tableColumn.setPreferredWidth(preferredWidth);
608 String proxyTypeString = Cache.getDefault("USE_PROXY", "false");
609 previousProxyType = proxyTypeString;
610 switch (proxyTypeString)
612 case Cache.PROXYTYPE_NONE:
613 proxyType.setSelected(noProxy.getModel(), true);
615 case Cache.PROXYTYPE_SYSTEM:
616 proxyType.setSelected(systemProxy.getModel(), true);
618 case Cache.PROXYTYPE_CUSTOM:
619 proxyType.setSelected(customProxy.getModel(), true);
623 "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): "
626 proxyServerHttpTB.setText(Cache.getDefault("PROXY_SERVER", ""));
627 proxyPortHttpTB.setText(Cache.getDefault("PROXY_PORT", ""));
628 proxyServerHttpsTB.setText(Cache.getDefault("PROXY_SERVER_HTTPS", ""));
629 proxyPortHttpsTB.setText(Cache.getDefault("PROXY_PORT_HTTPS", ""));
630 proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false));
632 .setText(Cache.getDefault("PROXY_AUTH_USERNAME", ""));
633 // we are not storing or retrieving proxy password from .jalview_properties
634 proxyAuthPasswordPB.setText(Cache.proxyAuthPassword == null ? ""
635 : new String(Cache.proxyAuthPassword));
636 setCustomProxyEnabled();
637 applyProxyButtonEnabled(false);
639 defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", ""));
641 usagestats.setSelected(Cache.getDefault("USAGESTATS", false));
642 // note antisense here: default is true
644 .setSelected(Cache.getProperty("NOQUESTIONNAIRES") == null);
645 versioncheck.setSelected(Cache.getDefault("VERSION_CHECK", true));
648 * Set Output tab defaults
650 setupOutputCombo(epsRendering, "EPS_RENDERING");
651 setupOutputCombo(htmlRendering, "HTML_RENDERING");
652 setupOutputCombo(svgRendering, "SVG_RENDERING");
653 autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false));
654 userIdWidth.setEnabled(!autoIdWidth.isSelected());
655 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
656 Integer wi = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH");
657 userIdWidth.setText(wi == null ? "" : wi.toString());
658 // TODO: refactor to use common enum via FormatAdapter and allow extension
659 // for new flat file formats
660 blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
661 clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
662 fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
663 msfjv.setSelected(Cache.getDefault("MSF_JVSUFFIX", true));
664 pfamjv.setSelected(Cache.getDefault("PFAM_JVSUFFIX", true));
665 pileupjv.setSelected(Cache.getDefault("PILEUP_JVSUFFIX", true));
666 pirjv.setSelected(Cache.getDefault("PIR_JVSUFFIX", true));
667 modellerOutput.setSelected(Cache.getDefault("PIR_MODELLER", false));
669 .setSelected(Cache.getDefault("EXPORT_EMBBED_BIOJSON", true));
672 * Set Editing tab defaults
674 autoCalculateConsCheck
675 .setSelected(Cache.getDefault("AUTO_CALC_CONSENSUS", true));
676 padGaps.setSelected(Cache.getDefault("PAD_GAPS", false));
677 sortByTree.setSelected(Cache.getDefault("SORT_BY_TREE", false));
679 annotations_actionPerformed(null); // update the display of the annotation
683 * Set Backups tab defaults
685 loadLastSavedBackupsOptions();
689 * A helper method that sets the items and initial selection in a character
690 * rendering option list (Prompt each time/Lineart/Text)
695 protected void setupOutputCombo(JComboBox<Object> comboBox,
698 comboBox.addItem(promptEachTimeOpt);
699 comboBox.addItem(lineArtOpt);
700 comboBox.addItem(textOpt);
703 * JalviewJS doesn't support Lineart so force it to Text
705 String defaultOption = Platform.isJS() ? "Text"
706 : Cache.getDefault(propertyKey, "Prompt each time");
707 if (defaultOption.equalsIgnoreCase("Text"))
709 comboBox.setSelectedItem(textOpt);
711 else if (defaultOption.equalsIgnoreCase("Lineart"))
713 comboBox.setSelectedItem(lineArtOpt);
717 comboBox.setSelectedItem(promptEachTimeOpt);
722 * Save user selections on the Preferences tabs to the Cache and write out to
728 public void ok_actionPerformed(ActionEvent e)
730 if (!validateSettings())
736 * Set proxy settings first (to be before web services refresh)
741 * Save Visual settings
743 Cache.applicationProperties.setProperty("SHOW_JVSUFFIX",
744 Boolean.toString(seqLimit.isSelected()));
745 Cache.applicationProperties.setProperty("RIGHT_ALIGN_IDS",
746 Boolean.toString(rightAlign.isSelected()));
747 Cache.applicationProperties.setProperty("SHOW_FULLSCREEN",
748 Boolean.toString(fullScreen.isSelected()));
749 Cache.applicationProperties.setProperty("SHOW_OVERVIEW",
750 Boolean.toString(openoverv.isSelected()));
751 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
752 Boolean.toString(annotations.isSelected()));
753 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
754 Boolean.toString(conservation.isSelected()));
755 Cache.applicationProperties.setProperty("SHOW_QUALITY",
756 Boolean.toString(quality.isSelected()));
757 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
758 Boolean.toString(identity.isSelected()));
760 Cache.applicationProperties.setProperty("GAP_SYMBOL",
761 gapSymbolCB.getSelectedItem().toString());
763 Cache.applicationProperties.setProperty("FONT_NAME",
764 fontNameCB.getSelectedItem().toString());
765 Cache.applicationProperties.setProperty("FONT_STYLE",
766 fontStyleCB.getSelectedItem().toString());
767 Cache.applicationProperties.setProperty("FONT_SIZE",
768 fontSizeCB.getSelectedItem().toString());
770 Cache.applicationProperties.setProperty("ID_ITALICS",
771 Boolean.toString(idItalics.isSelected()));
772 Cache.applicationProperties.setProperty("SHOW_UNCONSERVED",
773 Boolean.toString(showUnconserved.isSelected()));
774 Cache.applicationProperties.setProperty(SHOW_OCCUPANCY,
775 Boolean.toString(showOccupancy.isSelected()));
776 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSENSUS",
777 Boolean.toString(showGroupConsensus.isSelected()));
778 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSERVATION",
779 Boolean.toString(showGroupConservation.isSelected()));
780 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_HISTOGRAM",
781 Boolean.toString(showConsensHistogram.isSelected()));
782 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
783 Boolean.toString(showConsensLogo.isSelected()));
784 Cache.applicationProperties.setProperty("ANTI_ALIAS",
785 Boolean.toString(smoothFont.isSelected()));
786 Cache.applicationProperties.setProperty(SCALE_PROTEIN_TO_CDNA,
787 Boolean.toString(scaleProteinToCdna.isSelected()));
788 Cache.applicationProperties.setProperty("SHOW_NPFEATS_TOOLTIP",
789 Boolean.toString(showNpTooltip.isSelected()));
790 Cache.applicationProperties.setProperty("SHOW_DBREFS_TOOLTIP",
791 Boolean.toString(showDbRefTooltip.isSelected()));
793 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT",
794 Boolean.toString(wrap.isSelected()));
796 Cache.applicationProperties.setProperty("STARTUP_FILE",
797 startupFileTextfield.getText());
798 Cache.applicationProperties.setProperty("SHOW_STARTUP_FILE",
799 Boolean.toString(startupCheckbox.isSelected()));
801 Cache.applicationProperties.setProperty("SORT_ALIGNMENT",
802 sortby.getSelectedItem().toString());
804 // convert description of sort order to enum name for save
805 SequenceAnnotationOrder annSortOrder = SequenceAnnotationOrder
806 .forDescription(sortAnnBy.getSelectedItem().toString());
807 if (annSortOrder != null)
809 Cache.applicationProperties.setProperty(SORT_ANNOTATIONS,
810 annSortOrder.name());
813 final boolean showAutocalcFirst = sortAutocalc.getSelectedIndex() == 0;
814 Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE,
815 Boolean.valueOf(showAutocalcFirst).toString());
818 * Save Colours settings
820 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_PROT,
821 protColour.getSelectedItem().toString());
822 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_NUC,
823 nucColour.getSelectedItem().toString());
824 Cache.setColourProperty("ANNOTATIONCOLOUR_MIN",
825 minColour.getBackground());
826 Cache.setColourProperty("ANNOTATIONCOLOUR_MAX",
827 maxColour.getBackground());
830 * Save Overview settings
832 Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
833 Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
834 Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
835 Boolean.toString(useLegacyGap.isSelected()));
836 Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
837 Boolean.toString(showHiddenAtStart.isSelected()));
840 * Save Structure settings
842 Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
843 Boolean.toString(addTempFactor.isSelected()));
844 Cache.applicationProperties.setProperty(ADD_SS_ANN,
845 Boolean.toString(addSecondaryStructure.isSelected()));
846 Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
847 Boolean.toString(structFromPdb.isSelected()));
848 String viewer = structViewer.getSelectedItem().toString();
849 String viewerPath = structureViewerPath.getText();
850 Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, viewer);
851 if (viewer.equals(ViewerType.CHIMERA.name()))
853 Cache.setOrRemove(CHIMERA_PATH, viewerPath);
855 else if (viewer.equals(ViewerType.CHIMERAX.name()))
857 Cache.setOrRemove(CHIMERAX_PATH, viewerPath);
859 else if (viewer.equals(ViewerType.PYMOL.name()))
861 Cache.setOrRemove(PYMOL_PATH, viewerPath);
863 Cache.applicationProperties.setProperty("MAP_WITH_SIFTS",
864 Boolean.toString(siftsMapping.isSelected()));
865 SiftsSettings.setMapWithSifts(siftsMapping.isSelected());
868 * Save Output settings
870 Cache.applicationProperties.setProperty("EPS_RENDERING",
871 ((OptionsParam) epsRendering.getSelectedItem()).getCode());
872 Cache.applicationProperties.setProperty("HTML_RENDERING",
873 ((OptionsParam) htmlRendering.getSelectedItem()).getCode());
874 Cache.applicationProperties.setProperty("SVG_RENDERING",
875 ((OptionsParam) svgRendering.getSelectedItem()).getCode());
878 * Save Connections settings
880 // Proxy settings set first (to catch web services)
882 Cache.setOrRemove("DEFAULT_BROWSER", defaultBrowser.getText());
884 jalview.util.BrowserLauncher.resetBrowser();
886 // save user-defined and selected links
887 String menuLinks = sequenceUrlLinks.writeUrlsAsString(true);
888 if (menuLinks.isEmpty())
890 Cache.applicationProperties.remove("SEQUENCE_LINKS");
894 Cache.applicationProperties.setProperty("SEQUENCE_LINKS",
895 menuLinks.toString());
898 String nonMenuLinks = sequenceUrlLinks.writeUrlsAsString(false);
899 if (nonMenuLinks.isEmpty())
901 Cache.applicationProperties.remove("STORED_LINKS");
905 Cache.applicationProperties.setProperty("STORED_LINKS",
906 nonMenuLinks.toString());
909 Cache.applicationProperties.setProperty("DEFAULT_URL",
910 sequenceUrlLinks.getPrimaryUrlId());
912 Cache.setProperty("VERSION_CHECK",
913 Boolean.toString(versioncheck.isSelected()));
914 if (Cache.getProperty("USAGESTATS") != null || usagestats.isSelected())
916 // default is false - we only set this if the user has actively agreed
917 Cache.setProperty("USAGESTATS",
918 Boolean.toString(usagestats.isSelected()));
920 if (!questionnaire.isSelected())
922 Cache.setProperty("NOQUESTIONNAIRES", "true");
926 // special - made easy to edit a property file to disable questionnaires
927 // by just adding the given line
928 Cache.removeProperty("NOQUESTIONNAIRES");
932 * Save Output settings
934 Cache.applicationProperties.setProperty("BLC_JVSUFFIX",
935 Boolean.toString(blcjv.isSelected()));
936 Cache.applicationProperties.setProperty("CLUSTAL_JVSUFFIX",
937 Boolean.toString(clustaljv.isSelected()));
938 Cache.applicationProperties.setProperty("FASTA_JVSUFFIX",
939 Boolean.toString(fastajv.isSelected()));
940 Cache.applicationProperties.setProperty("MSF_JVSUFFIX",
941 Boolean.toString(msfjv.isSelected()));
942 Cache.applicationProperties.setProperty("PFAM_JVSUFFIX",
943 Boolean.toString(pfamjv.isSelected()));
944 Cache.applicationProperties.setProperty("PILEUP_JVSUFFIX",
945 Boolean.toString(pileupjv.isSelected()));
946 Cache.applicationProperties.setProperty("PIR_JVSUFFIX",
947 Boolean.toString(pirjv.isSelected()));
948 Cache.applicationProperties.setProperty("PIR_MODELLER",
949 Boolean.toString(modellerOutput.isSelected()));
950 Cache.applicationProperties.setProperty("EXPORT_EMBBED_BIOJSON",
951 Boolean.toString(embbedBioJSON.isSelected()));
952 jalview.io.PIRFile.useModellerOutput = modellerOutput.isSelected();
954 Cache.applicationProperties.setProperty("FIGURE_AUTOIDWIDTH",
955 Boolean.toString(autoIdWidth.isSelected()));
956 userIdWidth_actionPerformed();
957 Cache.applicationProperties.setProperty("FIGURE_FIXEDIDWIDTH",
958 userIdWidth.getText());
961 * Save Editing settings
963 Cache.applicationProperties.setProperty("AUTO_CALC_CONSENSUS",
964 Boolean.toString(autoCalculateConsCheck.isSelected()));
965 Cache.applicationProperties.setProperty("SORT_BY_TREE",
966 Boolean.toString(sortByTree.isSelected()));
967 Cache.applicationProperties.setProperty("PAD_GAPS",
968 Boolean.toString(padGaps.isSelected()));
970 if (!Platform.isJS())
972 wsPrefs.updateAndRefreshWsMenuConfig(false);
976 * Save Backups settings
978 Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
979 Boolean.toString(enableBackupFiles.isSelected()));
980 int preset = getComboIntStringKey(backupfilesPresetsCombo);
981 Cache.applicationProperties.setProperty(BackupFiles.NS + "_PRESET",
982 Integer.toString(preset));
984 if (preset == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
986 BackupFilesPresetEntry customBFPE = getBackupfilesCurrentEntry();
987 BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
988 BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM, customBFPE);
989 Cache.applicationProperties.setProperty(
990 BackupFilesPresetEntry.CUSTOMCONFIG, customBFPE.toString());
993 BackupFilesPresetEntry savedBFPE = BackupFilesPresetEntry.backupfilesPresetEntriesValues
995 Cache.applicationProperties.setProperty(
996 BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
998 Cache.saveProperties();
999 Desktop.instance.doConfigureStructurePrefs();
1002 frame.setClosed(true);
1003 } catch (Exception ex)
1008 public void saveProxySettings()
1010 String newProxyType = customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM
1011 : noProxy.isSelected() ? Cache.PROXYTYPE_NONE
1012 : Cache.PROXYTYPE_SYSTEM;
1013 Cache.applicationProperties.setProperty("USE_PROXY", newProxyType);
1014 Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText());
1015 Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText());
1016 Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText());
1017 Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText());
1018 Cache.setOrRemove("PROXY_AUTH",
1019 Boolean.toString(proxyAuth.isSelected()));
1020 Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText());
1021 Cache.proxyAuthPassword = proxyAuthPasswordPB.getPassword();
1022 Cache.setProxyPropertiesFromPreferences(previousProxyType);
1023 if (newProxyType.equals(Cache.PROXYTYPE_CUSTOM)
1024 || !newProxyType.equals(previousProxyType))
1026 // force a re-lookup of ws if proxytype is custom or has changed
1029 previousProxyType = newProxyType;
1033 * Do any necessary validation before saving settings. Return focus to the first
1034 * tab which fails validation.
1038 private boolean validateSettings()
1040 if (!validateStructure())
1042 structureTab.requestFocusInWindow();
1049 protected boolean validateStructure()
1051 return validateViewerPath();
1059 public void startupFileTextfield_mouseClicked()
1061 // TODO: JAL-3048 not needed for Jalview-JS
1062 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1063 JalviewFileChooser chooser = JalviewFileChooser
1064 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1065 chooser.setFileView(new JalviewFileView());
1066 chooser.setDialogTitle(
1067 MessageManager.getString("label.select_startup_file"));
1069 int value = chooser.showOpenDialog(this);
1071 if (value == JalviewFileChooser.APPROVE_OPTION)
1073 FileFormatI format = chooser.getSelectedFormat();
1076 Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
1079 startupFileTextfield
1080 .setText(chooser.getSelectedFile().getAbsolutePath());
1091 public void cancel_actionPerformed(ActionEvent e)
1095 if (!Platform.isJS())
1097 wsPrefs.updateWsMenuConfig(true);
1098 wsPrefs.refreshWs_actionPerformed(e);
1100 frame.setClosed(true);
1101 } catch (Exception ex)
1113 public void annotations_actionPerformed(ActionEvent e)
1115 conservation.setEnabled(annotations.isSelected());
1116 quality.setEnabled(annotations.isSelected());
1117 identity.setEnabled(annotations.isSelected());
1118 showOccupancy.setEnabled(annotations.isSelected());
1119 showGroupConsensus.setEnabled(annotations.isSelected());
1120 showGroupConservation.setEnabled(annotations.isSelected());
1121 showConsensHistogram.setEnabled(annotations.isSelected()
1122 && (identity.isSelected() || showGroupConsensus.isSelected()));
1123 showConsensLogo.setEnabled(annotations.isSelected()
1124 && (identity.isSelected() || showGroupConsensus.isSelected()));
1128 public void newLink_actionPerformed(ActionEvent e)
1130 GSequenceLink link = new GSequenceLink();
1131 boolean valid = false;
1134 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1135 MessageManager.getString("label.new_sequence_url_link"),
1136 JvOptionPane.OK_CANCEL_OPTION, -1,
1137 null) == JvOptionPane.OK_OPTION)
1139 if (link.checkValid())
1141 if (((UrlLinkTableModel) linkUrlTable.getModel())
1142 .isUniqueName(link.getName()))
1144 ((UrlLinkTableModel) linkUrlTable.getModel())
1145 .insertRow(link.getName(), link.getURL());
1150 link.notifyDuplicate();
1163 public void editLink_actionPerformed(ActionEvent e)
1165 GSequenceLink link = new GSequenceLink();
1167 int index = linkUrlTable.getSelectedRow();
1170 // button no longer enabled if row is not selected
1171 Cache.log.debug("Edit with no row selected in linkUrlTable");
1175 int nameCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1177 int urlCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1179 String oldName = linkUrlTable.getValueAt(index, nameCol).toString();
1180 link.setName(oldName);
1181 link.setURL(linkUrlTable.getValueAt(index, urlCol).toString());
1183 boolean valid = false;
1186 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1187 MessageManager.getString("label.edit_sequence_url_link"),
1188 JvOptionPane.OK_CANCEL_OPTION, -1,
1189 null) == JvOptionPane.OK_OPTION)
1191 if (link.checkValid())
1193 if ((oldName.equals(link.getName()))
1194 || (((UrlLinkTableModel) linkUrlTable.getModel())
1195 .isUniqueName(link.getName())))
1197 linkUrlTable.setValueAt(link.getName(), index, nameCol);
1198 linkUrlTable.setValueAt(link.getURL(), index, urlCol);
1203 link.notifyDuplicate();
1216 public void deleteLink_actionPerformed(ActionEvent e)
1218 int index = linkUrlTable.getSelectedRow();
1219 int modelIndex = -1;
1222 // button no longer enabled if row is not selected
1223 Cache.log.debug("Delete with no row selected in linkUrlTable");
1228 modelIndex = linkUrlTable.convertRowIndexToModel(index);
1231 // make sure we use the model index to delete, and not the table index
1232 ((UrlLinkTableModel) linkUrlTable.getModel()).removeRow(modelIndex);
1236 public void defaultBrowser_mouseClicked(MouseEvent e)
1238 // TODO: JAL-3048 not needed for j2s
1239 if (!Platform.isJS()) // BH 2019
1246 JFileChooser chooser = new JFileChooser(".");
1247 chooser.setDialogTitle(
1248 MessageManager.getString("label.select_default_browser"));
1250 int value = chooser.showOpenDialog(this);
1252 if (value == JFileChooser.APPROVE_OPTION)
1254 defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath());
1263 * jalview.jbgui.GPreferences#showunconserved_actionPerformed(java.awt.event
1267 protected void showunconserved_actionPerformed(ActionEvent e)
1269 // TODO Auto-generated method stub
1270 super.showunconserved_actionPerformed(e);
1273 public static List<String> getGroupURLLinks()
1275 return groupURLLinks;
1279 public void minColour_actionPerformed(JPanel panel)
1281 JalviewColourChooser.showColourChooser(this,
1282 MessageManager.getString("label.select_colour_minimum_value"),
1287 public void maxColour_actionPerformed(JPanel panel)
1289 JalviewColourChooser.showColourChooser(this,
1290 MessageManager.getString("label.select_colour_maximum_value"),
1295 public void gapColour_actionPerformed(JPanel gap)
1297 if (!useLegacyGap.isSelected())
1299 JalviewColourChooser.showColourChooser(this,
1300 MessageManager.getString("label.select_gap_colour"), gap);
1305 public void hiddenColour_actionPerformed(JPanel hidden)
1307 JalviewColourChooser.showColourChooser(this,
1308 MessageManager.getString("label.select_hidden_colour"), hidden);
1312 protected void useLegacyGaps_actionPerformed(ActionEvent e)
1314 boolean enabled = useLegacyGap.isSelected();
1317 gapColour.setBackground(
1318 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
1322 gapColour.setBackground(
1323 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
1325 gapColour.setEnabled(!enabled);
1326 gapLabel.setEnabled(!enabled);
1330 protected void resetOvDefaults_actionPerformed(ActionEvent e)
1332 useLegacyGap.setSelected(false);
1333 useLegacyGaps_actionPerformed(null);
1334 showHiddenAtStart.setSelected(false);
1335 hiddenColour.setBackground(
1336 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
1340 protected void userIdWidth_actionPerformed()
1344 String val = userIdWidth.getText().trim();
1345 if (val.length() > 0)
1347 Integer iw = Integer.parseInt(val);
1348 if (iw.intValue() < 12)
1350 throw new NumberFormatException();
1352 userIdWidth.setText(iw.toString());
1354 } catch (NumberFormatException x)
1356 userIdWidth.setText("");
1357 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1359 .getString("warn.user_defined_width_requirements"),
1360 MessageManager.getString("label.invalid_id_column_width"),
1361 JvOptionPane.WARNING_MESSAGE);
1366 protected void autoIdWidth_actionPerformed()
1368 userIdWidth.setEnabled(!autoIdWidth.isSelected());
1369 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
1373 * Returns true if structure viewer path is to a valid executable, else shows an
1374 * error dialog. Does nothing if the path is empty, as is the case for Jmol
1375 * (built in to Jalview) or when Jalview is left to try default paths.
1377 private boolean validateViewerPath()
1379 if (structureViewerPath.getText().trim().length() > 0)
1381 File f = new File(structureViewerPath.getText());
1382 if (!f.canExecute())
1384 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1385 MessageManager.getString("label.invalid_viewer_path"),
1386 MessageManager.getString("label.invalid_viewer_path"),
1387 JvOptionPane.ERROR_MESSAGE);
1395 * If Chimera or ChimeraX or Pymol is selected, check it can be found on default
1396 * or user-specified path, if not show a warning/help dialog
1399 protected void structureViewer_actionPerformed(String selectedItem)
1401 if (selectedItem.equals(ViewerType.JMOL.name()))
1403 structureViewerPath.setEnabled(false);
1404 structureViewerPathLabel.setEnabled(false);
1407 boolean found = false;
1408 structureViewerPath.setEnabled(true);
1409 structureViewerPathLabel.setEnabled(true);
1410 structureViewerPathLabel.setText(MessageManager
1411 .formatMessage("label.viewer_path", selectedItem));
1414 * Try user-specified and standard paths for structure viewer executable
1416 String viewerPath = "";
1417 List<String> paths = null;
1420 ViewerType viewerType = ViewerType.valueOf(selectedItem);
1427 viewerPath = Cache.getDefault(CHIMERA_PATH, "");
1428 paths = StructureManager.getChimeraPaths(false);
1431 viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
1432 paths = StructureManager.getChimeraPaths(true);
1435 viewerPath = Cache.getDefault(PYMOL_PATH, "");
1436 paths = PymolManager.getPymolPaths();
1439 } catch (IllegalArgumentException e)
1441 // only valid entries should be in the drop-down
1443 structureViewerPath.setText(viewerPath);
1445 paths.add(0, structureViewerPath.getText());
1446 for (String path : paths)
1448 if (new File(path.trim()).canExecute())
1457 String[] options = { "OK", "Help" };
1458 int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
1459 JvSwingUtils.wrapTooltip(true,
1460 MessageManager.getString("label.viewer_missing")),
1461 "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
1462 null, options, options[0]);
1464 if (showHelp == JvOptionPane.NO_OPTION)
1466 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1469 Help.showHelpWindow(HelpId.StructureViewer);
1470 } catch (HelpSetException e)
1472 e.printStackTrace();
1475 else if (showHelp == JvOptionPane.OK_OPTION)
1477 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1478 CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
1481 for (int i = 0; i < 3; i++)
1483 structureViewerPath.setBackground(Color.PINK);
1485 structureViewerPath.setBackground(Color.WHITE);
1488 } catch (InterruptedException e)
1496 public class OptionsParam
1498 private String name;
1500 private String code;
1502 public OptionsParam(String name, String code)
1508 public String getName()
1513 public void setName(String name)
1518 public String getCode()
1523 public void setCode(String code)
1529 public String toString()
1535 public boolean equals(Object that)
1537 if (!(that instanceof OptionsParam))
1541 return this.code.equalsIgnoreCase(((OptionsParam) that).code);
1545 public int hashCode()
1547 return name.hashCode() + code.hashCode();
1551 private class UrlListSelectionHandler implements ListSelectionListener
1555 public void valueChanged(ListSelectionEvent e)
1557 ListSelectionModel lsm = (ListSelectionModel) e.getSource();
1559 int index = lsm.getMinSelectionIndex();
1562 // no selection, so disable delete/edit buttons
1563 editLink.setEnabled(false);
1564 deleteLink.setEnabled(false);
1567 int modelIndex = linkUrlTable.convertRowIndexToModel(index);
1569 // enable/disable edit and delete link buttons
1570 if (((UrlLinkTableModel) linkUrlTable.getModel())
1571 .isRowDeletable(modelIndex))
1573 deleteLink.setEnabled(true);
1577 deleteLink.setEnabled(false);
1580 if (((UrlLinkTableModel) linkUrlTable.getModel())
1581 .isRowEditable(modelIndex))
1583 editLink.setEnabled(true);
1587 editLink.setEnabled(false);