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, false);
400 structFromPdb.setSelected(structSelected);
401 useRnaView.setSelected(Cache.getDefault(USE_RNAVIEW, false));
402 useRnaView.setEnabled(structSelected);
403 addSecondaryStructure.setSelected(Cache.getDefault(ADD_SS_ANN, false));
404 addSecondaryStructure.setEnabled(structSelected);
405 addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false));
406 addTempFactor.setEnabled(structSelected);
409 * set choice of structure viewer, and path if saved as a preference;
410 * default to Jmol (first choice) if an unexpected value is found
412 String viewerType = Cache.getDefault(STRUCTURE_DISPLAY,
413 ViewerType.JMOL.name());
414 structViewer.setSelectedItem(viewerType);
415 String viewerPath = "";
416 ViewerType type = null;
419 type = ViewerType.valueOf(viewerType);
425 viewerPath = Cache.getDefault(CHIMERA_PATH, "");
428 viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
431 viewerPath = Cache.getDefault(PYMOL_PATH, "");
434 } catch (IllegalArgumentException e)
436 Cache.log.error("Unknown structure viewer type: " + viewerType
437 + ", defaulting to Jmol");
438 type = ViewerType.JMOL;
440 structureViewerPath.setText(viewerPath);
442 structureViewerPath.addActionListener(new ActionListener()
445 public void actionPerformed(ActionEvent e)
447 if (validateViewerPath())
449 String path = structureViewerPath.getText();
451 ViewerType type = ViewerType.valueOf(viewerType);
457 Cache.setProperty(CHIMERA_PATH, path);
460 Cache.setProperty(CHIMERAX_PATH, path);
463 Cache.setProperty(PYMOL_PATH, path);
466 } catch (IllegalArgumentException x)
468 Cache.log.error("Failed to set path - unknown viewer type",x);
474 if (Cache.getDefault("MAP_WITH_SIFTS", false))
476 siftsMapping.setSelected(true);
480 nwMapping.setSelected(true);
484 .setMapWithSifts(Cache.getDefault("MAP_WITH_SIFTS", false));
487 * Set Connections tab defaults
491 linkUrlTable.setModel(dataModel);
492 final TableRowSorter<TableModel> sorter = new TableRowSorter<>(
493 linkUrlTable.getModel());
494 linkUrlTable.setRowSorter(sorter);
495 List<RowSorter.SortKey> sortKeys = new ArrayList<>();
497 UrlLinkTableModel m = (UrlLinkTableModel) linkUrlTable.getModel();
498 sortKeys.add(new RowSorter.SortKey(m.getPrimaryColumn(),
499 SortOrder.DESCENDING));
500 sortKeys.add(new RowSorter.SortKey(m.getSelectedColumn(),
501 SortOrder.DESCENDING));
503 new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING));
505 sorter.setSortKeys(sortKeys);
506 // BH 2018 setSortKeys will do the sort
510 ActionListener onReset;
511 onReset = new ActionListener()
514 public void actionPerformed(ActionEvent e)
516 filterTB.setText("");
517 sorter.setRowFilter(RowFilter.regexFilter(""));
521 doReset.addActionListener(onReset);
523 // filter to display only custom urls
524 final RowFilter<TableModel, Object> customUrlFilter = new RowFilter<TableModel, Object>()
527 public boolean include(
528 Entry<? extends TableModel, ? extends Object> entry)
530 return ((UrlLinkTableModel) entry.getModel()).isUserEntry(entry);
534 final TableRowSorter<TableModel> customSorter = new TableRowSorter<>(
535 linkUrlTable.getModel());
536 customSorter.setRowFilter(customUrlFilter);
538 ActionListener onCustomOnly;
539 onCustomOnly = new ActionListener()
542 public void actionPerformed(ActionEvent e)
544 filterTB.setText("");
545 sorter.setRowFilter(customUrlFilter);
548 userOnly.addActionListener(onCustomOnly);
550 filterTB.getDocument().addDocumentListener(new DocumentListener()
552 String caseInsensitiveFlag = "(?i)";
555 public void changedUpdate(DocumentEvent e)
557 sorter.setRowFilter(RowFilter
558 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
562 public void removeUpdate(DocumentEvent e)
564 sorter.setRowFilter(RowFilter
565 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
569 public void insertUpdate(DocumentEvent e)
571 sorter.setRowFilter(RowFilter
572 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
576 // set up list selection functionality
577 linkUrlTable.getSelectionModel()
578 .addListSelectionListener(new UrlListSelectionHandler());
580 // set up radio buttons
581 int onClickCol = ((UrlLinkTableModel) linkUrlTable.getModel())
583 String onClickName = linkUrlTable.getColumnName(onClickCol);
584 linkUrlTable.getColumn(onClickName)
585 .setCellRenderer(new RadioButtonRenderer());
586 linkUrlTable.getColumn(onClickName)
587 .setCellEditor(new RadioButtonEditor());
589 // get boolean columns and resize those to min possible
590 for (int column = 0; column < linkUrlTable.getColumnCount(); column++)
592 if (linkUrlTable.getModel().getColumnClass(column)
593 .equals(Boolean.class))
595 TableColumn tableColumn = linkUrlTable.getColumnModel()
597 int preferredWidth = tableColumn.getMinWidth();
599 TableCellRenderer cellRenderer = linkUrlTable.getCellRenderer(0,
601 Component c = linkUrlTable.prepareRenderer(cellRenderer, 0, column);
602 int cwidth = c.getPreferredSize().width
603 + linkUrlTable.getIntercellSpacing().width;
604 preferredWidth = Math.max(preferredWidth, cwidth);
606 tableColumn.setPreferredWidth(preferredWidth);
610 String proxyTypeString = Cache.getDefault("USE_PROXY", "false");
611 previousProxyType = proxyTypeString;
612 switch (proxyTypeString)
614 case Cache.PROXYTYPE_NONE:
615 proxyType.setSelected(noProxy.getModel(), true);
617 case Cache.PROXYTYPE_SYSTEM:
618 proxyType.setSelected(systemProxy.getModel(), true);
620 case Cache.PROXYTYPE_CUSTOM:
621 proxyType.setSelected(customProxy.getModel(), true);
625 "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): "
628 proxyServerHttpTB.setText(Cache.getDefault("PROXY_SERVER", ""));
629 proxyPortHttpTB.setText(Cache.getDefault("PROXY_PORT", ""));
630 proxyServerHttpsTB.setText(Cache.getDefault("PROXY_SERVER_HTTPS", ""));
631 proxyPortHttpsTB.setText(Cache.getDefault("PROXY_PORT_HTTPS", ""));
632 proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false));
634 .setText(Cache.getDefault("PROXY_AUTH_USERNAME", ""));
635 // we are not storing or retrieving proxy password from .jalview_properties
636 proxyAuthPasswordPB.setText(Cache.proxyAuthPassword == null ? ""
637 : new String(Cache.proxyAuthPassword));
638 setCustomProxyEnabled();
639 applyProxyButtonEnabled(false);
641 defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", ""));
643 usagestats.setSelected(Cache.getDefault("USAGESTATS", false));
644 // note antisense here: default is true
646 .setSelected(Cache.getProperty("NOQUESTIONNAIRES") == null);
647 versioncheck.setSelected(Cache.getDefault("VERSION_CHECK", true));
650 * Set Output tab defaults
652 setupOutputCombo(epsRendering, "EPS_RENDERING");
653 setupOutputCombo(htmlRendering, "HTML_RENDERING");
654 setupOutputCombo(svgRendering, "SVG_RENDERING");
655 autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false));
656 userIdWidth.setEnabled(!autoIdWidth.isSelected());
657 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
658 Integer wi = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH");
659 userIdWidth.setText(wi == null ? "" : wi.toString());
660 // TODO: refactor to use common enum via FormatAdapter and allow extension
661 // for new flat file formats
662 blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
663 clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
664 fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
665 msfjv.setSelected(Cache.getDefault("MSF_JVSUFFIX", true));
666 pfamjv.setSelected(Cache.getDefault("PFAM_JVSUFFIX", true));
667 pileupjv.setSelected(Cache.getDefault("PILEUP_JVSUFFIX", true));
668 pirjv.setSelected(Cache.getDefault("PIR_JVSUFFIX", true));
669 modellerOutput.setSelected(Cache.getDefault("PIR_MODELLER", false));
671 .setSelected(Cache.getDefault("EXPORT_EMBBED_BIOJSON", true));
674 * Set Editing tab defaults
676 autoCalculateConsCheck
677 .setSelected(Cache.getDefault("AUTO_CALC_CONSENSUS", true));
678 padGaps.setSelected(Cache.getDefault("PAD_GAPS", false));
679 sortByTree.setSelected(Cache.getDefault("SORT_BY_TREE", false));
681 annotations_actionPerformed(null); // update the display of the annotation
685 * Set Backups tab defaults
687 loadLastSavedBackupsOptions();
691 * A helper method that sets the items and initial selection in a character
692 * rendering option list (Prompt each time/Lineart/Text)
697 protected void setupOutputCombo(JComboBox<Object> comboBox,
700 comboBox.addItem(promptEachTimeOpt);
701 comboBox.addItem(lineArtOpt);
702 comboBox.addItem(textOpt);
705 * JalviewJS doesn't support Lineart so force it to Text
707 String defaultOption = Platform.isJS() ? "Text"
708 : Cache.getDefault(propertyKey, "Prompt each time");
709 if (defaultOption.equalsIgnoreCase("Text"))
711 comboBox.setSelectedItem(textOpt);
713 else if (defaultOption.equalsIgnoreCase("Lineart"))
715 comboBox.setSelectedItem(lineArtOpt);
719 comboBox.setSelectedItem(promptEachTimeOpt);
724 * Save user selections on the Preferences tabs to the Cache and write out to
730 public void ok_actionPerformed(ActionEvent e)
732 if (!validateSettings())
738 * Set proxy settings first (to be before web services refresh)
743 * Save Visual settings
745 Cache.applicationProperties.setProperty("SHOW_JVSUFFIX",
746 Boolean.toString(seqLimit.isSelected()));
747 Cache.applicationProperties.setProperty("RIGHT_ALIGN_IDS",
748 Boolean.toString(rightAlign.isSelected()));
749 Cache.applicationProperties.setProperty("SHOW_FULLSCREEN",
750 Boolean.toString(fullScreen.isSelected()));
751 Cache.applicationProperties.setProperty("SHOW_OVERVIEW",
752 Boolean.toString(openoverv.isSelected()));
753 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
754 Boolean.toString(annotations.isSelected()));
755 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
756 Boolean.toString(conservation.isSelected()));
757 Cache.applicationProperties.setProperty("SHOW_QUALITY",
758 Boolean.toString(quality.isSelected()));
759 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
760 Boolean.toString(identity.isSelected()));
762 Cache.applicationProperties.setProperty("GAP_SYMBOL",
763 gapSymbolCB.getSelectedItem().toString());
765 Cache.applicationProperties.setProperty("FONT_NAME",
766 fontNameCB.getSelectedItem().toString());
767 Cache.applicationProperties.setProperty("FONT_STYLE",
768 fontStyleCB.getSelectedItem().toString());
769 Cache.applicationProperties.setProperty("FONT_SIZE",
770 fontSizeCB.getSelectedItem().toString());
772 Cache.applicationProperties.setProperty("ID_ITALICS",
773 Boolean.toString(idItalics.isSelected()));
774 Cache.applicationProperties.setProperty("SHOW_UNCONSERVED",
775 Boolean.toString(showUnconserved.isSelected()));
776 Cache.applicationProperties.setProperty(SHOW_OCCUPANCY,
777 Boolean.toString(showOccupancy.isSelected()));
778 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSENSUS",
779 Boolean.toString(showGroupConsensus.isSelected()));
780 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSERVATION",
781 Boolean.toString(showGroupConservation.isSelected()));
782 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_HISTOGRAM",
783 Boolean.toString(showConsensHistogram.isSelected()));
784 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
785 Boolean.toString(showConsensLogo.isSelected()));
786 Cache.applicationProperties.setProperty("ANTI_ALIAS",
787 Boolean.toString(smoothFont.isSelected()));
788 Cache.applicationProperties.setProperty(SCALE_PROTEIN_TO_CDNA,
789 Boolean.toString(scaleProteinToCdna.isSelected()));
790 Cache.applicationProperties.setProperty("SHOW_NPFEATS_TOOLTIP",
791 Boolean.toString(showNpTooltip.isSelected()));
792 Cache.applicationProperties.setProperty("SHOW_DBREFS_TOOLTIP",
793 Boolean.toString(showDbRefTooltip.isSelected()));
795 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT",
796 Boolean.toString(wrap.isSelected()));
798 Cache.applicationProperties.setProperty("STARTUP_FILE",
799 startupFileTextfield.getText());
800 Cache.applicationProperties.setProperty("SHOW_STARTUP_FILE",
801 Boolean.toString(startupCheckbox.isSelected()));
803 Cache.applicationProperties.setProperty("SORT_ALIGNMENT",
804 sortby.getSelectedItem().toString());
806 // convert description of sort order to enum name for save
807 SequenceAnnotationOrder annSortOrder = SequenceAnnotationOrder
808 .forDescription(sortAnnBy.getSelectedItem().toString());
809 if (annSortOrder != null)
811 Cache.applicationProperties.setProperty(SORT_ANNOTATIONS,
812 annSortOrder.name());
815 final boolean showAutocalcFirst = sortAutocalc.getSelectedIndex() == 0;
816 Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE,
817 Boolean.valueOf(showAutocalcFirst).toString());
820 * Save Colours settings
822 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_PROT,
823 protColour.getSelectedItem().toString());
824 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_NUC,
825 nucColour.getSelectedItem().toString());
826 Cache.setColourProperty("ANNOTATIONCOLOUR_MIN",
827 minColour.getBackground());
828 Cache.setColourProperty("ANNOTATIONCOLOUR_MAX",
829 maxColour.getBackground());
832 * Save Overview settings
834 Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
835 Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
836 Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
837 Boolean.toString(useLegacyGap.isSelected()));
838 Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
839 Boolean.toString(showHiddenAtStart.isSelected()));
842 * Save Structure settings
844 Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
845 Boolean.toString(addTempFactor.isSelected()));
846 Cache.applicationProperties.setProperty(ADD_SS_ANN,
847 Boolean.toString(addSecondaryStructure.isSelected()));
848 Cache.applicationProperties.setProperty(USE_RNAVIEW,
849 Boolean.toString(useRnaView.isSelected()));
850 Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
851 Boolean.toString(structFromPdb.isSelected()));
852 String viewer = structViewer.getSelectedItem().toString();
853 String viewerPath = structureViewerPath.getText();
854 Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, viewer);
855 if (viewer.equals(ViewerType.CHIMERA.name()))
857 Cache.setOrRemove(CHIMERA_PATH, viewerPath);
859 else if (viewer.equals(ViewerType.CHIMERAX.name()))
861 Cache.setOrRemove(CHIMERAX_PATH, viewerPath);
863 else if (viewer.equals(ViewerType.PYMOL.name()))
865 Cache.setOrRemove(PYMOL_PATH, viewerPath);
867 Cache.applicationProperties.setProperty("MAP_WITH_SIFTS",
868 Boolean.toString(siftsMapping.isSelected()));
869 SiftsSettings.setMapWithSifts(siftsMapping.isSelected());
872 * Save Output settings
874 Cache.applicationProperties.setProperty("EPS_RENDERING",
875 ((OptionsParam) epsRendering.getSelectedItem()).getCode());
876 Cache.applicationProperties.setProperty("HTML_RENDERING",
877 ((OptionsParam) htmlRendering.getSelectedItem()).getCode());
878 Cache.applicationProperties.setProperty("SVG_RENDERING",
879 ((OptionsParam) svgRendering.getSelectedItem()).getCode());
882 * Save Connections settings
884 // Proxy settings set first (to catch web services)
886 Cache.setOrRemove("DEFAULT_BROWSER", defaultBrowser.getText());
888 jalview.util.BrowserLauncher.resetBrowser();
890 // save user-defined and selected links
891 String menuLinks = sequenceUrlLinks.writeUrlsAsString(true);
892 if (menuLinks.isEmpty())
894 Cache.applicationProperties.remove("SEQUENCE_LINKS");
898 Cache.applicationProperties.setProperty("SEQUENCE_LINKS",
899 menuLinks.toString());
902 String nonMenuLinks = sequenceUrlLinks.writeUrlsAsString(false);
903 if (nonMenuLinks.isEmpty())
905 Cache.applicationProperties.remove("STORED_LINKS");
909 Cache.applicationProperties.setProperty("STORED_LINKS",
910 nonMenuLinks.toString());
913 Cache.applicationProperties.setProperty("DEFAULT_URL",
914 sequenceUrlLinks.getPrimaryUrlId());
916 Cache.setProperty("VERSION_CHECK",
917 Boolean.toString(versioncheck.isSelected()));
918 if (Cache.getProperty("USAGESTATS") != null || usagestats.isSelected())
920 // default is false - we only set this if the user has actively agreed
921 Cache.setProperty("USAGESTATS",
922 Boolean.toString(usagestats.isSelected()));
924 if (!questionnaire.isSelected())
926 Cache.setProperty("NOQUESTIONNAIRES", "true");
930 // special - made easy to edit a property file to disable questionnaires
931 // by just adding the given line
932 Cache.removeProperty("NOQUESTIONNAIRES");
936 * Save Output settings
938 Cache.applicationProperties.setProperty("BLC_JVSUFFIX",
939 Boolean.toString(blcjv.isSelected()));
940 Cache.applicationProperties.setProperty("CLUSTAL_JVSUFFIX",
941 Boolean.toString(clustaljv.isSelected()));
942 Cache.applicationProperties.setProperty("FASTA_JVSUFFIX",
943 Boolean.toString(fastajv.isSelected()));
944 Cache.applicationProperties.setProperty("MSF_JVSUFFIX",
945 Boolean.toString(msfjv.isSelected()));
946 Cache.applicationProperties.setProperty("PFAM_JVSUFFIX",
947 Boolean.toString(pfamjv.isSelected()));
948 Cache.applicationProperties.setProperty("PILEUP_JVSUFFIX",
949 Boolean.toString(pileupjv.isSelected()));
950 Cache.applicationProperties.setProperty("PIR_JVSUFFIX",
951 Boolean.toString(pirjv.isSelected()));
952 Cache.applicationProperties.setProperty("PIR_MODELLER",
953 Boolean.toString(modellerOutput.isSelected()));
954 Cache.applicationProperties.setProperty("EXPORT_EMBBED_BIOJSON",
955 Boolean.toString(embbedBioJSON.isSelected()));
956 jalview.io.PIRFile.useModellerOutput = modellerOutput.isSelected();
958 Cache.applicationProperties.setProperty("FIGURE_AUTOIDWIDTH",
959 Boolean.toString(autoIdWidth.isSelected()));
960 userIdWidth_actionPerformed();
961 Cache.applicationProperties.setProperty("FIGURE_FIXEDIDWIDTH",
962 userIdWidth.getText());
965 * Save Editing settings
967 Cache.applicationProperties.setProperty("AUTO_CALC_CONSENSUS",
968 Boolean.toString(autoCalculateConsCheck.isSelected()));
969 Cache.applicationProperties.setProperty("SORT_BY_TREE",
970 Boolean.toString(sortByTree.isSelected()));
971 Cache.applicationProperties.setProperty("PAD_GAPS",
972 Boolean.toString(padGaps.isSelected()));
974 if (!Platform.isJS())
976 wsPrefs.updateAndRefreshWsMenuConfig(false);
980 * Save Backups settings
982 Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
983 Boolean.toString(enableBackupFiles.isSelected()));
984 int preset = getComboIntStringKey(backupfilesPresetsCombo);
985 Cache.applicationProperties.setProperty(BackupFiles.NS + "_PRESET",
986 Integer.toString(preset));
988 if (preset == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
990 BackupFilesPresetEntry customBFPE = getBackupfilesCurrentEntry();
991 BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
992 BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM, customBFPE);
993 Cache.applicationProperties.setProperty(
994 BackupFilesPresetEntry.CUSTOMCONFIG, customBFPE.toString());
997 BackupFilesPresetEntry savedBFPE = BackupFilesPresetEntry.backupfilesPresetEntriesValues
999 Cache.applicationProperties.setProperty(
1000 BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
1002 Cache.saveProperties();
1003 Desktop.instance.doConfigureStructurePrefs();
1006 frame.setClosed(true);
1007 } catch (Exception ex)
1012 public void saveProxySettings()
1014 String newProxyType = customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM
1015 : noProxy.isSelected() ? Cache.PROXYTYPE_NONE
1016 : Cache.PROXYTYPE_SYSTEM;
1017 Cache.applicationProperties.setProperty("USE_PROXY", newProxyType);
1018 Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText());
1019 Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText());
1020 Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText());
1021 Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText());
1022 Cache.setOrRemove("PROXY_AUTH",
1023 Boolean.toString(proxyAuth.isSelected()));
1024 Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText());
1025 Cache.proxyAuthPassword = proxyAuthPasswordPB.getPassword();
1026 Cache.setProxyPropertiesFromPreferences(previousProxyType);
1027 if (newProxyType.equals(Cache.PROXYTYPE_CUSTOM)
1028 || !newProxyType.equals(previousProxyType))
1030 // force a re-lookup of ws if proxytype is custom or has changed
1033 previousProxyType = newProxyType;
1037 * Do any necessary validation before saving settings. Return focus to the first
1038 * tab which fails validation.
1042 private boolean validateSettings()
1044 if (!validateStructure())
1046 structureTab.requestFocusInWindow();
1053 protected boolean validateStructure()
1055 return validateViewerPath();
1063 public void startupFileTextfield_mouseClicked()
1065 // TODO: JAL-3048 not needed for Jalview-JS
1066 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1067 JalviewFileChooser chooser = JalviewFileChooser
1068 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1069 chooser.setFileView(new JalviewFileView());
1070 chooser.setDialogTitle(
1071 MessageManager.getString("label.select_startup_file"));
1073 int value = chooser.showOpenDialog(this);
1075 if (value == JalviewFileChooser.APPROVE_OPTION)
1077 FileFormatI format = chooser.getSelectedFormat();
1080 Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
1083 startupFileTextfield
1084 .setText(chooser.getSelectedFile().getAbsolutePath());
1095 public void cancel_actionPerformed(ActionEvent e)
1099 if (!Platform.isJS())
1101 wsPrefs.updateWsMenuConfig(true);
1102 wsPrefs.refreshWs_actionPerformed(e);
1104 frame.setClosed(true);
1105 } catch (Exception ex)
1117 public void annotations_actionPerformed(ActionEvent e)
1119 conservation.setEnabled(annotations.isSelected());
1120 quality.setEnabled(annotations.isSelected());
1121 identity.setEnabled(annotations.isSelected());
1122 showOccupancy.setEnabled(annotations.isSelected());
1123 showGroupConsensus.setEnabled(annotations.isSelected());
1124 showGroupConservation.setEnabled(annotations.isSelected());
1125 showConsensHistogram.setEnabled(annotations.isSelected()
1126 && (identity.isSelected() || showGroupConsensus.isSelected()));
1127 showConsensLogo.setEnabled(annotations.isSelected()
1128 && (identity.isSelected() || showGroupConsensus.isSelected()));
1132 public void newLink_actionPerformed(ActionEvent e)
1134 GSequenceLink link = new GSequenceLink();
1135 boolean valid = false;
1138 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1139 MessageManager.getString("label.new_sequence_url_link"),
1140 JvOptionPane.OK_CANCEL_OPTION, -1,
1141 null) == JvOptionPane.OK_OPTION)
1143 if (link.checkValid())
1145 if (((UrlLinkTableModel) linkUrlTable.getModel())
1146 .isUniqueName(link.getName()))
1148 ((UrlLinkTableModel) linkUrlTable.getModel())
1149 .insertRow(link.getName(), link.getURL());
1154 link.notifyDuplicate();
1167 public void editLink_actionPerformed(ActionEvent e)
1169 GSequenceLink link = new GSequenceLink();
1171 int index = linkUrlTable.getSelectedRow();
1174 // button no longer enabled if row is not selected
1175 Cache.log.debug("Edit with no row selected in linkUrlTable");
1179 int nameCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1181 int urlCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1183 String oldName = linkUrlTable.getValueAt(index, nameCol).toString();
1184 link.setName(oldName);
1185 link.setURL(linkUrlTable.getValueAt(index, urlCol).toString());
1187 boolean valid = false;
1190 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1191 MessageManager.getString("label.edit_sequence_url_link"),
1192 JvOptionPane.OK_CANCEL_OPTION, -1,
1193 null) == JvOptionPane.OK_OPTION)
1195 if (link.checkValid())
1197 if ((oldName.equals(link.getName()))
1198 || (((UrlLinkTableModel) linkUrlTable.getModel())
1199 .isUniqueName(link.getName())))
1201 linkUrlTable.setValueAt(link.getName(), index, nameCol);
1202 linkUrlTable.setValueAt(link.getURL(), index, urlCol);
1207 link.notifyDuplicate();
1220 public void deleteLink_actionPerformed(ActionEvent e)
1222 int index = linkUrlTable.getSelectedRow();
1223 int modelIndex = -1;
1226 // button no longer enabled if row is not selected
1227 Cache.log.debug("Delete with no row selected in linkUrlTable");
1232 modelIndex = linkUrlTable.convertRowIndexToModel(index);
1235 // make sure we use the model index to delete, and not the table index
1236 ((UrlLinkTableModel) linkUrlTable.getModel()).removeRow(modelIndex);
1240 public void defaultBrowser_mouseClicked(MouseEvent e)
1242 // TODO: JAL-3048 not needed for j2s
1243 if (!Platform.isJS()) // BH 2019
1250 JFileChooser chooser = new JFileChooser(".");
1251 chooser.setDialogTitle(
1252 MessageManager.getString("label.select_default_browser"));
1254 int value = chooser.showOpenDialog(this);
1256 if (value == JFileChooser.APPROVE_OPTION)
1258 defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath());
1267 * jalview.jbgui.GPreferences#showunconserved_actionPerformed(java.awt.event
1271 protected void showunconserved_actionPerformed(ActionEvent e)
1273 // TODO Auto-generated method stub
1274 super.showunconserved_actionPerformed(e);
1277 public static List<String> getGroupURLLinks()
1279 return groupURLLinks;
1283 public void minColour_actionPerformed(JPanel panel)
1285 JalviewColourChooser.showColourChooser(this,
1286 MessageManager.getString("label.select_colour_minimum_value"),
1291 public void maxColour_actionPerformed(JPanel panel)
1293 JalviewColourChooser.showColourChooser(this,
1294 MessageManager.getString("label.select_colour_maximum_value"),
1299 public void gapColour_actionPerformed(JPanel gap)
1301 if (!useLegacyGap.isSelected())
1303 JalviewColourChooser.showColourChooser(this,
1304 MessageManager.getString("label.select_gap_colour"), gap);
1309 public void hiddenColour_actionPerformed(JPanel hidden)
1311 JalviewColourChooser.showColourChooser(this,
1312 MessageManager.getString("label.select_hidden_colour"), hidden);
1316 protected void useLegacyGaps_actionPerformed(ActionEvent e)
1318 boolean enabled = useLegacyGap.isSelected();
1321 gapColour.setBackground(
1322 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
1326 gapColour.setBackground(
1327 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
1329 gapColour.setEnabled(!enabled);
1330 gapLabel.setEnabled(!enabled);
1334 protected void resetOvDefaults_actionPerformed(ActionEvent e)
1336 useLegacyGap.setSelected(false);
1337 useLegacyGaps_actionPerformed(null);
1338 showHiddenAtStart.setSelected(false);
1339 hiddenColour.setBackground(
1340 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
1344 protected void userIdWidth_actionPerformed()
1348 String val = userIdWidth.getText().trim();
1349 if (val.length() > 0)
1351 Integer iw = Integer.parseInt(val);
1352 if (iw.intValue() < 12)
1354 throw new NumberFormatException();
1356 userIdWidth.setText(iw.toString());
1358 } catch (NumberFormatException x)
1360 userIdWidth.setText("");
1361 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1363 .getString("warn.user_defined_width_requirements"),
1364 MessageManager.getString("label.invalid_id_column_width"),
1365 JvOptionPane.WARNING_MESSAGE);
1370 protected void autoIdWidth_actionPerformed()
1372 userIdWidth.setEnabled(!autoIdWidth.isSelected());
1373 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
1377 * Returns true if structure viewer path is to a valid executable, else shows an
1378 * error dialog. Does nothing if the path is empty, as is the case for Jmol
1379 * (built in to Jalview) or when Jalview is left to try default paths.
1381 private boolean validateViewerPath()
1383 if (structureViewerPath.getText().trim().length() > 0)
1385 File f = new File(structureViewerPath.getText());
1386 if (!f.canExecute())
1388 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1389 MessageManager.getString("label.invalid_viewer_path"),
1390 MessageManager.getString("label.invalid_viewer_path"),
1391 JvOptionPane.ERROR_MESSAGE);
1399 * If Chimera or ChimeraX or Pymol is selected, check it can be found on default
1400 * or user-specified path, if not show a warning/help dialog
1403 protected void structureViewer_actionPerformed(String selectedItem)
1405 if (selectedItem.equals(ViewerType.JMOL.name()))
1407 structureViewerPath.setEnabled(false);
1408 structureViewerPathLabel.setEnabled(false);
1411 boolean found = false;
1412 structureViewerPath.setEnabled(true);
1413 structureViewerPathLabel.setEnabled(true);
1414 structureViewerPathLabel.setText(MessageManager
1415 .formatMessage("label.viewer_path", selectedItem));
1418 * Try user-specified and standard paths for structure viewer executable
1420 String viewerPath = "";
1421 List<String> paths = null;
1424 ViewerType viewerType = ViewerType.valueOf(selectedItem);
1431 viewerPath = Cache.getDefault(CHIMERA_PATH, "");
1432 paths = StructureManager.getChimeraPaths(false);
1435 viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
1436 paths = StructureManager.getChimeraPaths(true);
1439 viewerPath = Cache.getDefault(PYMOL_PATH, "");
1440 paths = PymolManager.getPymolPaths();
1443 } catch (IllegalArgumentException e)
1445 // only valid entries should be in the drop-down
1447 structureViewerPath.setText(viewerPath);
1449 paths.add(0, structureViewerPath.getText());
1450 for (String path : paths)
1452 if (new File(path.trim()).canExecute())
1461 String[] options = { "OK", "Help" };
1462 int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
1463 JvSwingUtils.wrapTooltip(true,
1464 MessageManager.getString("label.viewer_missing")),
1465 "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
1466 null, options, options[0]);
1468 if (showHelp == JvOptionPane.NO_OPTION)
1470 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1473 Help.showHelpWindow(HelpId.StructureViewer);
1474 } catch (HelpSetException e)
1476 e.printStackTrace();
1479 else if (showHelp == JvOptionPane.OK_OPTION)
1481 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1482 CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
1485 for (int i = 0; i < 3; i++)
1487 structureViewerPath.setBackground(Color.PINK);
1489 structureViewerPath.setBackground(Color.WHITE);
1492 } catch (InterruptedException e)
1500 public class OptionsParam
1502 private String name;
1504 private String code;
1506 public OptionsParam(String name, String code)
1512 public String getName()
1517 public void setName(String name)
1522 public String getCode()
1527 public void setCode(String code)
1533 public String toString()
1539 public boolean equals(Object that)
1541 if (!(that instanceof OptionsParam))
1545 return this.code.equalsIgnoreCase(((OptionsParam) that).code);
1549 public int hashCode()
1551 return name.hashCode() + code.hashCode();
1555 private class UrlListSelectionHandler implements ListSelectionListener
1559 public void valueChanged(ListSelectionEvent e)
1561 ListSelectionModel lsm = (ListSelectionModel) e.getSource();
1563 int index = lsm.getMinSelectionIndex();
1566 // no selection, so disable delete/edit buttons
1567 editLink.setEnabled(false);
1568 deleteLink.setEnabled(false);
1571 int modelIndex = linkUrlTable.convertRowIndexToModel(index);
1573 // enable/disable edit and delete link buttons
1574 if (((UrlLinkTableModel) linkUrlTable.getModel())
1575 .isRowDeletable(modelIndex))
1577 deleteLink.setEnabled(true);
1581 deleteLink.setEnabled(false);
1584 if (((UrlLinkTableModel) linkUrlTable.getModel())
1585 .isRowEditable(modelIndex))
1587 editLink.setEnabled(true);
1591 editLink.setEnabled(false);