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;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.CompletableFuture;
35 import javax.help.HelpSetException;
36 import javax.swing.JComboBox;
37 import javax.swing.JInternalFrame;
38 import javax.swing.JPanel;
39 import javax.swing.ListSelectionModel;
40 import javax.swing.RowFilter;
41 import javax.swing.RowSorter;
42 import javax.swing.SortOrder;
43 import javax.swing.event.DocumentEvent;
44 import javax.swing.event.DocumentListener;
45 import javax.swing.event.ListSelectionEvent;
46 import javax.swing.event.ListSelectionListener;
47 import javax.swing.table.TableCellRenderer;
48 import javax.swing.table.TableColumn;
49 import javax.swing.table.TableModel;
50 import javax.swing.table.TableRowSorter;
52 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
53 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
54 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
55 import jalview.bin.Cache;
56 import jalview.bin.Console;
57 import jalview.bin.MemorySetting;
58 import jalview.ext.pymol.PymolManager;
59 import jalview.gui.Help.HelpId;
60 import jalview.gui.StructureViewer.ViewerType;
61 import jalview.io.BackupFiles;
62 import jalview.io.BackupFilesPresetEntry;
63 import jalview.io.FileFormatI;
64 import jalview.io.JalviewFileChooser;
65 import jalview.io.JalviewFileView;
66 import jalview.jbgui.GPreferences;
67 import jalview.jbgui.GSequenceLink;
68 import jalview.schemes.ColourSchemeI;
69 import jalview.schemes.ColourSchemes;
70 import jalview.schemes.ResidueColourScheme;
71 import jalview.urls.UrlLinkTableModel;
72 import jalview.urls.api.UrlProviderFactoryI;
73 import jalview.urls.api.UrlProviderI;
74 import jalview.urls.desktop.DesktopUrlProviderFactory;
75 import jalview.util.MessageManager;
76 import jalview.util.Platform;
77 import jalview.util.UrlConstants;
78 import jalview.ws.sifts.SiftsSettings;
87 * for merge with Jalview-JS
88 public class Preferences extends GPreferences implements ApplicationSingletonI
90 public class Preferences extends GPreferences
92 public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
94 public static final String SCALE_PROTEIN_TO_CDNA = "SCALE_PROTEIN_TO_CDNA";
96 public static final String DEFAULT_COLOUR = "DEFAULT_COLOUR";
98 public static final String DEFAULT_COLOUR_PROT = "DEFAULT_COLOUR_PROT";
100 public static final String DEFAULT_COLOUR_NUC = "DEFAULT_COLOUR_NUC";
102 public static final String ADD_TEMPFACT_ANN = "ADD_TEMPFACT_ANN";
104 public static final String ADD_SS_ANN = "ADD_SS_ANN";
106 public static final String USE_RNAVIEW = "USE_RNAVIEW";
108 public static final String STRUCT_FROM_PDB = "STRUCT_FROM_PDB";
110 public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
112 public static final String CHIMERA_PATH = "CHIMERA_PATH";
114 public static final String CHIMERAX_PATH = "CHIMERAX_PATH";
116 public static final String PYMOL_PATH = "PYMOL_PATH";
118 public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
120 public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
122 public static final String SHOW_OCCUPANCY = "SHOW_OCCUPANCY";
124 public static final String SHOW_OV_HIDDEN_AT_START = "SHOW_OV_HIDDEN_AT_START";
126 public static final String USE_LEGACY_GAP = "USE_LEGACY_GAP";
128 public static final String GAP_COLOUR = "GAP_COLOUR";
130 public static final String HIDDEN_COLOUR = "HIDDEN_COLOUR";
132 private static final int MIN_FONT_SIZE = 1;
134 private static final int MAX_FONT_SIZE = 30;
136 private String previousProxyType;
138 private static Preferences INSTANCE = null; // add "final"
141 * Holds name and link separated with | character. Sequence ID must be
142 * $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$
144 public static UrlProviderI sequenceUrlLinks;
146 public static UrlLinkTableModel dataModel;
149 * Holds name and link separated with | character. Sequence IDS and Sequences
150 * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and
151 * $SEQUENCES$ or $SEQUENCES=/.possible | chars ./=$ and separation character
152 * for first and second token specified after a pipe character at end |,|.
153 * (TODO: proper escape for using | to separate ids or sequences
156 public static List<String> groupURLLinks;
159 // get links selected to be in the menu (SEQUENCE_LINKS)
160 // and links entered by the user but not selected (STORED_LINKS)
161 String inMenuString = Cache.getDefault("SEQUENCE_LINKS", "");
162 String notInMenuString = Cache.getDefault("STORED_LINKS", "");
163 String defaultUrl = Cache.getDefault("DEFAULT_URL",
164 UrlConstants.DEFAULT_LABEL);
166 // if both links lists are empty, add the DEFAULT_URL link
167 // otherwise we assume the default link is in one of the lists
168 if (inMenuString.isEmpty() && notInMenuString.isEmpty())
170 inMenuString = UrlConstants.DEFAULT_STRING;
172 UrlProviderFactoryI factory = new DesktopUrlProviderFactory(defaultUrl,
173 inMenuString, notInMenuString);
174 sequenceUrlLinks = factory.createUrlProvider();
175 dataModel = new UrlLinkTableModel(sequenceUrlLinks);
178 * TODO: reformulate groupURL encoding so two or more can be stored in the
179 * .properties file as '|' separated strings
182 groupURLLinks = new ArrayList<>();
185 JInternalFrame frame;
187 private WsPreferences wsPrefs;
189 private OptionsParam promptEachTimeOpt = new OptionsParam(
190 MessageManager.getString("label.prompt_each_time"),
193 private OptionsParam lineArtOpt = new OptionsParam(
194 MessageManager.getString("label.lineart"), "Lineart");
196 private OptionsParam textOpt = new OptionsParam(
197 MessageManager.getString("action.text"), "Text");
199 // get singleton Preferences instance
200 public static Preferences getInstance()
202 if (INSTANCE == null || INSTANCE.frame == null
203 || INSTANCE.frame.isClosed())
205 INSTANCE = new Preferences();
210 * Replace code with the following for Jalvew-JS
211 Preferences INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
212 if (INSTANCE == null || INSTANCE.frame == null
213 || INSTANCE.frame.isClosed())
215 ApplicationSingletonProvider.remove(Preferences.class);
216 INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
222 public static void openPreferences()
224 openPreferences(null, null);
227 public static void openPreferences(TabRef selectTab, String message)
229 Preferences p = getInstance();
230 if (selectTab != null)
231 p.selectTab(selectTab, message);
233 p.frame.moveToFront();
237 public void selectTab(TabRef selectTab, String message)
239 this.selectTab(selectTab);
241 this.setMessage(message);
246 * Creates a new Preferences object.
248 private Preferences()
251 frame = new JInternalFrame();
252 frame.setFrameIcon(WindowIcons.preferencesIcon);
253 frame.setContentPane(this);
254 if (!Platform.isJS())
261 wsPrefs = new WsPreferences();
262 wsTab.add(wsPrefs, BorderLayout.CENTER);
264 int width = 500, height = 450;
265 if (Platform.isAMacAndNotJS())
271 Desktop.addInternalFrame(frame,
272 MessageManager.getString("label.preferences"), width, height);
273 frame.setMinimumSize(new Dimension(width, height));
276 * Set Visual tab defaults
278 seqLimit.setSelected(Cache.getDefault("SHOW_JVSUFFIX", true));
279 rightAlign.setSelected(Cache.getDefault("RIGHT_ALIGN_IDS", false));
280 fullScreen.setSelected(Cache.getDefault("SHOW_FULLSCREEN", false));
281 annotations.setSelected(Cache.getDefault("SHOW_ANNOTATIONS", true));
283 conservation.setSelected(Cache.getDefault("SHOW_CONSERVATION", true));
284 quality.setSelected(Cache.getDefault("SHOW_QUALITY", true));
285 identity.setSelected(Cache.getDefault("SHOW_IDENTITY", true));
286 openoverv.setSelected(Cache.getDefault("SHOW_OVERVIEW", false));
288 .setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
289 showOccupancy.setSelected(Cache.getDefault(SHOW_OCCUPANCY, false));
291 .setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS", false));
292 showGroupConservation.setSelected(
293 Cache.getDefault("SHOW_GROUP_CONSERVATION", false));
294 showConsensHistogram.setSelected(
295 Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
297 .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
299 .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
301 .setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP", true));
303 String[] fonts = java.awt.GraphicsEnvironment
304 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
305 for (int i = 0; i < fonts.length; i++)
307 fontNameCB.addItem(fonts[i]);
310 for (int i = MIN_FONT_SIZE; i <= MAX_FONT_SIZE; i++)
312 fontSizeCB.addItem(i + "");
315 fontStyleCB.addItem("plain");
316 fontStyleCB.addItem("bold");
317 fontStyleCB.addItem("italic");
319 fontNameCB.setSelectedItem(Cache.getDefault("FONT_NAME", "SansSerif"));
320 fontSizeCB.setSelectedItem(Cache.getDefault("FONT_SIZE", "10"));
321 fontStyleCB.setSelectedItem(
322 Cache.getDefault("FONT_STYLE", Font.PLAIN + ""));
324 smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", true));
326 .setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA, false));
328 idItalics.setSelected(Cache.getDefault("ID_ITALICS", true));
330 wrap.setSelected(Cache.getDefault("WRAP_ALIGNMENT", false));
332 gapSymbolCB.addItem("-");
333 gapSymbolCB.addItem(".");
335 gapSymbolCB.setSelectedItem(Cache.getDefault("GAP_SYMBOL", "-"));
337 sortby.addItem("No sort");
338 sortby.addItem("Id");
339 sortby.addItem("Pairwise Identity");
340 sortby.setSelectedItem(Cache.getDefault("SORT_ALIGNMENT", "No sort"));
342 sortAnnBy.addItem(SequenceAnnotationOrder.NONE.toString());
344 .addItem(SequenceAnnotationOrder.SEQUENCE_AND_LABEL.toString());
346 .addItem(SequenceAnnotationOrder.LABEL_AND_SEQUENCE.toString());
347 SequenceAnnotationOrder savedSort = SequenceAnnotationOrder
348 .valueOf(Cache.getDefault(SORT_ANNOTATIONS,
349 SequenceAnnotationOrder.NONE.name()));
350 sortAnnBy.setSelectedItem(savedSort.toString());
352 sortAutocalc.addItem("Autocalculated first");
353 sortAutocalc.addItem("Autocalculated last");
354 final boolean showAbove = Cache.getDefault(SHOW_AUTOCALC_ABOVE, true);
355 sortAutocalc.setSelectedItem(showAbove ? sortAutocalc.getItemAt(0)
356 : sortAutocalc.getItemAt(1));
358 .setSelected(Cache.getDefault("SHOW_STARTUP_FILE", true));
359 startupFileTextfield.setText(Cache.getDefault("STARTUP_FILE",
360 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
361 + "/examples/exampleFile_2_7.jvp"));
364 * Set Colours tab defaults
366 protColour.addItem(ResidueColourScheme.NONE);
367 nucColour.addItem(ResidueColourScheme.NONE);
368 for (ColourSchemeI cs : ColourSchemes.getInstance().getColourSchemes())
370 String name = cs.getSchemeName();
371 protColour.addItem(name);
372 nucColour.addItem(name);
374 String oldProp = Cache.getDefault(DEFAULT_COLOUR,
375 ResidueColourScheme.NONE);
376 String newProp = Cache.getDefault(DEFAULT_COLOUR_PROT, null);
377 protColour.setSelectedItem(newProp != null ? newProp : oldProp);
378 newProp = Cache.getDefault(DEFAULT_COLOUR_NUC, null);
379 nucColour.setSelectedItem(newProp != null ? newProp : oldProp);
380 minColour.setBackground(
381 Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
382 maxColour.setBackground(
383 Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
386 * Set overview panel defaults
388 gapColour.setBackground(Cache.getDefaultColour(GAP_COLOUR,
389 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP));
390 hiddenColour.setBackground(Cache.getDefaultColour(HIDDEN_COLOUR,
391 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN));
392 useLegacyGap.setSelected(Cache.getDefault(USE_LEGACY_GAP, false));
393 gapLabel.setEnabled(!useLegacyGap.isSelected());
394 gapColour.setEnabled(!useLegacyGap.isSelected());
396 .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, false));
399 * Set Structure tab defaults
401 final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, true);
402 structFromPdb.setSelected(structSelected);
403 addSecondaryStructure.setSelected(Cache.getDefault(ADD_SS_ANN, true));
404 addSecondaryStructure.setEnabled(structSelected);
405 addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, true));
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 Console.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();
452 ViewerType type = ViewerType.valueOf(viewerType);
458 Cache.setProperty(CHIMERA_PATH, path);
461 Cache.setProperty(CHIMERAX_PATH, path);
464 Cache.setProperty(PYMOL_PATH, path);
467 } catch (IllegalArgumentException x)
469 Console.error("Failed to set path - unknown viewer type", x);
475 if (Cache.getDefault("MAP_WITH_SIFTS", false))
477 siftsMapping.setSelected(true);
481 nwMapping.setSelected(true);
485 .setMapWithSifts(Cache.getDefault("MAP_WITH_SIFTS", false));
488 * Set Connections tab defaults
492 linkUrlTable.setModel(dataModel);
493 final TableRowSorter<TableModel> sorter = new TableRowSorter<>(
494 linkUrlTable.getModel());
495 linkUrlTable.setRowSorter(sorter);
496 List<RowSorter.SortKey> sortKeys = new ArrayList<>();
498 UrlLinkTableModel m = (UrlLinkTableModel) linkUrlTable.getModel();
499 sortKeys.add(new RowSorter.SortKey(m.getPrimaryColumn(),
500 SortOrder.DESCENDING));
501 sortKeys.add(new RowSorter.SortKey(m.getSelectedColumn(),
502 SortOrder.DESCENDING));
504 new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING));
506 sorter.setSortKeys(sortKeys);
507 // BH 2018 setSortKeys will do the sort
511 ActionListener onReset;
512 onReset = new ActionListener()
515 public void actionPerformed(ActionEvent e)
517 filterTB.setText("");
518 sorter.setRowFilter(RowFilter.regexFilter(""));
522 doReset.addActionListener(onReset);
524 // filter to display only custom urls
525 final RowFilter<TableModel, Object> customUrlFilter = new RowFilter<TableModel, Object>()
528 public boolean include(
529 Entry<? extends TableModel, ? extends Object> entry)
531 return ((UrlLinkTableModel) entry.getModel()).isUserEntry(entry);
535 final TableRowSorter<TableModel> customSorter = new TableRowSorter<>(
536 linkUrlTable.getModel());
537 customSorter.setRowFilter(customUrlFilter);
539 ActionListener onCustomOnly;
540 onCustomOnly = new ActionListener()
543 public void actionPerformed(ActionEvent e)
545 filterTB.setText("");
546 sorter.setRowFilter(customUrlFilter);
549 userOnly.addActionListener(onCustomOnly);
551 filterTB.getDocument().addDocumentListener(new DocumentListener()
553 String caseInsensitiveFlag = "(?i)";
556 public void changedUpdate(DocumentEvent e)
558 sorter.setRowFilter(RowFilter
559 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
563 public void removeUpdate(DocumentEvent e)
565 sorter.setRowFilter(RowFilter
566 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
570 public void insertUpdate(DocumentEvent e)
572 sorter.setRowFilter(RowFilter
573 .regexFilter(caseInsensitiveFlag + filterTB.getText()));
577 // set up list selection functionality
578 linkUrlTable.getSelectionModel()
579 .addListSelectionListener(new UrlListSelectionHandler());
581 // set up radio buttons
582 int onClickCol = ((UrlLinkTableModel) linkUrlTable.getModel())
584 String onClickName = linkUrlTable.getColumnName(onClickCol);
585 linkUrlTable.getColumn(onClickName)
586 .setCellRenderer(new RadioButtonRenderer());
587 linkUrlTable.getColumn(onClickName)
588 .setCellEditor(new RadioButtonEditor());
590 // get boolean columns and resize those to min possible
591 for (int column = 0; column < linkUrlTable.getColumnCount(); column++)
593 if (linkUrlTable.getModel().getColumnClass(column)
594 .equals(Boolean.class))
596 TableColumn tableColumn = linkUrlTable.getColumnModel()
598 int preferredWidth = tableColumn.getMinWidth();
600 TableCellRenderer cellRenderer = linkUrlTable.getCellRenderer(0,
602 Component c = linkUrlTable.prepareRenderer(cellRenderer, 0, column);
603 int cwidth = c.getPreferredSize().width
604 + linkUrlTable.getIntercellSpacing().width;
605 preferredWidth = Math.max(preferredWidth, cwidth);
607 tableColumn.setPreferredWidth(preferredWidth);
611 String proxyTypeString = Cache.getDefault("USE_PROXY", "false");
612 previousProxyType = proxyTypeString;
613 switch (proxyTypeString)
615 case Cache.PROXYTYPE_NONE:
616 proxyType.setSelected(noProxy.getModel(), true);
618 case Cache.PROXYTYPE_SYSTEM:
619 proxyType.setSelected(systemProxy.getModel(), true);
621 case Cache.PROXYTYPE_CUSTOM:
622 proxyType.setSelected(customProxy.getModel(), true);
626 "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): "
629 proxyServerHttpTB.setText(Cache.getDefault("PROXY_SERVER", ""));
630 proxyPortHttpTB.setText(Cache.getDefault("PROXY_PORT", ""));
631 proxyServerHttpsTB.setText(Cache.getDefault("PROXY_SERVER_HTTPS", ""));
632 proxyPortHttpsTB.setText(Cache.getDefault("PROXY_PORT_HTTPS", ""));
633 proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false));
635 .setText(Cache.getDefault("PROXY_AUTH_USERNAME", ""));
636 // we are not storing or retrieving proxy password from .jalview_properties
637 proxyAuthPasswordPB.setText(Cache.proxyAuthPassword == null ? ""
638 : new String(Cache.proxyAuthPassword));
639 setCustomProxyEnabled();
640 applyProxyButtonEnabled(false);
642 usagestats.setSelected(Cache.getDefault("USAGESTATS", false));
643 // note antisense here: default is true
645 .setSelected(Cache.getProperty("NOQUESTIONNAIRES") == null);
646 versioncheck.setSelected(Cache.getDefault("VERSION_CHECK", true));
649 * Set Output tab defaults
651 setupOutputCombo(epsRendering, "EPS_RENDERING");
652 setupOutputCombo(htmlRendering, "HTML_RENDERING");
653 setupOutputCombo(svgRendering, "SVG_RENDERING");
654 autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false));
655 userIdWidth.setEnabled(!autoIdWidth.isSelected());
656 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
657 Integer wi = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH");
658 userIdWidth.setText(wi == null ? "" : wi.toString());
659 // TODO: refactor to use common enum via FormatAdapter and allow extension
660 // for new flat file formats
661 blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
662 clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
663 fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
664 msfjv.setSelected(Cache.getDefault("MSF_JVSUFFIX", true));
665 pfamjv.setSelected(Cache.getDefault("PFAM_JVSUFFIX", true));
666 pileupjv.setSelected(Cache.getDefault("PILEUP_JVSUFFIX", true));
667 pirjv.setSelected(Cache.getDefault("PIR_JVSUFFIX", true));
668 modellerOutput.setSelected(Cache.getDefault("PIR_MODELLER", false));
670 .setSelected(Cache.getDefault("EXPORT_EMBBED_BIOJSON", true));
673 * Set Editing tab defaults
675 autoCalculateConsCheck
676 .setSelected(Cache.getDefault("AUTO_CALC_CONSENSUS", true));
677 padGaps.setSelected(Cache.getDefault("PAD_GAPS", false));
678 sortByTree.setSelected(Cache.getDefault("SORT_BY_TREE", false));
680 annotations_actionPerformed(null); // update the display of the annotation
684 * Set Backups tab defaults
686 loadLastSavedBackupsOptions();
689 * Set Startup tab defaults
695 * A helper method that sets the items and initial selection in a character
696 * rendering option list (Prompt each time/Lineart/Text)
701 protected void setupOutputCombo(JComboBox<Object> comboBox,
704 comboBox.addItem(promptEachTimeOpt);
705 comboBox.addItem(lineArtOpt);
706 comboBox.addItem(textOpt);
709 * JalviewJS doesn't support Lineart so force it to Text
711 String defaultOption = Platform.isJS() ? "Text"
712 : Cache.getDefault(propertyKey, "Prompt each time");
713 if (defaultOption.equalsIgnoreCase("Text"))
715 comboBox.setSelectedItem(textOpt);
717 else if (defaultOption.equalsIgnoreCase("Lineart"))
719 comboBox.setSelectedItem(lineArtOpt);
723 comboBox.setSelectedItem(promptEachTimeOpt);
728 * Save user selections on the Preferences tabs to the Cache and write out to
734 public void ok_actionPerformed(ActionEvent e)
736 if (!validateSettings())
742 * Set proxy settings first (to be before web services refresh)
747 * Save Visual settings
749 Cache.applicationProperties.setProperty("SHOW_JVSUFFIX",
750 Boolean.toString(seqLimit.isSelected()));
751 Cache.applicationProperties.setProperty("RIGHT_ALIGN_IDS",
752 Boolean.toString(rightAlign.isSelected()));
753 Cache.applicationProperties.setProperty("SHOW_FULLSCREEN",
754 Boolean.toString(fullScreen.isSelected()));
755 Cache.applicationProperties.setProperty("SHOW_OVERVIEW",
756 Boolean.toString(openoverv.isSelected()));
757 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
758 Boolean.toString(annotations.isSelected()));
759 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
760 Boolean.toString(conservation.isSelected()));
761 Cache.applicationProperties.setProperty("SHOW_QUALITY",
762 Boolean.toString(quality.isSelected()));
763 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
764 Boolean.toString(identity.isSelected()));
766 Cache.applicationProperties.setProperty("GAP_SYMBOL",
767 gapSymbolCB.getSelectedItem().toString());
769 Cache.applicationProperties.setProperty("FONT_NAME",
770 fontNameCB.getSelectedItem().toString());
771 Cache.applicationProperties.setProperty("FONT_STYLE",
772 fontStyleCB.getSelectedItem().toString());
773 Cache.applicationProperties.setProperty("FONT_SIZE",
774 fontSizeCB.getSelectedItem().toString());
776 Cache.applicationProperties.setProperty("ID_ITALICS",
777 Boolean.toString(idItalics.isSelected()));
778 Cache.applicationProperties.setProperty("SHOW_UNCONSERVED",
779 Boolean.toString(showUnconserved.isSelected()));
780 Cache.applicationProperties.setProperty(SHOW_OCCUPANCY,
781 Boolean.toString(showOccupancy.isSelected()));
782 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSENSUS",
783 Boolean.toString(showGroupConsensus.isSelected()));
784 Cache.applicationProperties.setProperty("SHOW_GROUP_CONSERVATION",
785 Boolean.toString(showGroupConservation.isSelected()));
786 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_HISTOGRAM",
787 Boolean.toString(showConsensHistogram.isSelected()));
788 Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
789 Boolean.toString(showConsensLogo.isSelected()));
790 Cache.applicationProperties.setProperty("ANTI_ALIAS",
791 Boolean.toString(smoothFont.isSelected()));
792 Cache.applicationProperties.setProperty(SCALE_PROTEIN_TO_CDNA,
793 Boolean.toString(scaleProteinToCdna.isSelected()));
794 Cache.applicationProperties.setProperty("SHOW_NPFEATS_TOOLTIP",
795 Boolean.toString(showNpTooltip.isSelected()));
796 Cache.applicationProperties.setProperty("SHOW_DBREFS_TOOLTIP",
797 Boolean.toString(showDbRefTooltip.isSelected()));
799 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT",
800 Boolean.toString(wrap.isSelected()));
802 Cache.applicationProperties.setProperty("STARTUP_FILE",
803 startupFileTextfield.getText());
804 Cache.applicationProperties.setProperty("SHOW_STARTUP_FILE",
805 Boolean.toString(startupCheckbox.isSelected()));
807 Cache.applicationProperties.setProperty("SORT_ALIGNMENT",
808 sortby.getSelectedItem().toString());
810 // convert description of sort order to enum name for save
811 SequenceAnnotationOrder annSortOrder = SequenceAnnotationOrder
812 .forDescription(sortAnnBy.getSelectedItem().toString());
813 if (annSortOrder != null)
815 Cache.applicationProperties.setProperty(SORT_ANNOTATIONS,
816 annSortOrder.name());
819 final boolean showAutocalcFirst = sortAutocalc.getSelectedIndex() == 0;
820 Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE,
821 Boolean.valueOf(showAutocalcFirst).toString());
824 * Save Colours settings
826 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_PROT,
827 protColour.getSelectedItem().toString());
828 Cache.applicationProperties.setProperty(DEFAULT_COLOUR_NUC,
829 nucColour.getSelectedItem().toString());
830 Cache.setColourProperty("ANNOTATIONCOLOUR_MIN",
831 minColour.getBackground());
832 Cache.setColourProperty("ANNOTATIONCOLOUR_MAX",
833 maxColour.getBackground());
836 * Save Overview settings
838 Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
839 Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
840 Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
841 Boolean.toString(useLegacyGap.isSelected()));
842 Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
843 Boolean.toString(showHiddenAtStart.isSelected()));
846 * Save Structure settings
848 Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
849 Boolean.toString(addTempFactor.isSelected()));
850 Cache.applicationProperties.setProperty(ADD_SS_ANN,
851 Boolean.toString(addSecondaryStructure.isSelected()));
852 Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
853 Boolean.toString(structFromPdb.isSelected()));
854 String viewer = structViewer.getSelectedItem().toString();
855 String viewerPath = structureViewerPath.getText();
856 Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, viewer);
857 if (viewer.equals(ViewerType.CHIMERA.name()))
859 Cache.setOrRemove(CHIMERA_PATH, viewerPath);
861 else if (viewer.equals(ViewerType.CHIMERAX.name()))
863 Cache.setOrRemove(CHIMERAX_PATH, viewerPath);
865 else if (viewer.equals(ViewerType.PYMOL.name()))
867 Cache.setOrRemove(PYMOL_PATH, viewerPath);
869 Cache.applicationProperties.setProperty("MAP_WITH_SIFTS",
870 Boolean.toString(siftsMapping.isSelected()));
871 SiftsSettings.setMapWithSifts(siftsMapping.isSelected());
874 * Save Output settings
876 Cache.applicationProperties.setProperty("EPS_RENDERING",
877 ((OptionsParam) epsRendering.getSelectedItem()).getCode());
878 Cache.applicationProperties.setProperty("HTML_RENDERING",
879 ((OptionsParam) htmlRendering.getSelectedItem()).getCode());
880 Cache.applicationProperties.setProperty("SVG_RENDERING",
881 ((OptionsParam) svgRendering.getSelectedItem()).getCode());
884 * Save Connections settings
886 // Proxy settings set first (to catch web services)
888 // save user-defined and selected links
889 String menuLinks = sequenceUrlLinks.writeUrlsAsString(true);
890 if (menuLinks.isEmpty())
892 Cache.applicationProperties.remove("SEQUENCE_LINKS");
896 Cache.applicationProperties.setProperty("SEQUENCE_LINKS",
897 menuLinks.toString());
900 String nonMenuLinks = sequenceUrlLinks.writeUrlsAsString(false);
901 if (nonMenuLinks.isEmpty())
903 Cache.applicationProperties.remove("STORED_LINKS");
907 Cache.applicationProperties.setProperty("STORED_LINKS",
908 nonMenuLinks.toString());
911 Cache.applicationProperties.setProperty("DEFAULT_URL",
912 sequenceUrlLinks.getPrimaryUrlId());
914 Cache.setProperty("VERSION_CHECK",
915 Boolean.toString(versioncheck.isSelected()));
916 if (Cache.getProperty("USAGESTATS") != null || usagestats.isSelected())
918 // default is false - we only set this if the user has actively agreed
919 Cache.setProperty("USAGESTATS",
920 Boolean.toString(usagestats.isSelected()));
922 if (!questionnaire.isSelected())
924 Cache.setProperty("NOQUESTIONNAIRES", "true");
928 // special - made easy to edit a property file to disable questionnaires
929 // by just adding the given line
930 Cache.removeProperty("NOQUESTIONNAIRES");
934 * Save Output settings
936 Cache.applicationProperties.setProperty("BLC_JVSUFFIX",
937 Boolean.toString(blcjv.isSelected()));
938 Cache.applicationProperties.setProperty("CLUSTAL_JVSUFFIX",
939 Boolean.toString(clustaljv.isSelected()));
940 Cache.applicationProperties.setProperty("FASTA_JVSUFFIX",
941 Boolean.toString(fastajv.isSelected()));
942 Cache.applicationProperties.setProperty("MSF_JVSUFFIX",
943 Boolean.toString(msfjv.isSelected()));
944 Cache.applicationProperties.setProperty("PFAM_JVSUFFIX",
945 Boolean.toString(pfamjv.isSelected()));
946 Cache.applicationProperties.setProperty("PILEUP_JVSUFFIX",
947 Boolean.toString(pileupjv.isSelected()));
948 Cache.applicationProperties.setProperty("PIR_JVSUFFIX",
949 Boolean.toString(pirjv.isSelected()));
950 Cache.applicationProperties.setProperty("PIR_MODELLER",
951 Boolean.toString(modellerOutput.isSelected()));
952 Cache.applicationProperties.setProperty("EXPORT_EMBBED_BIOJSON",
953 Boolean.toString(embbedBioJSON.isSelected()));
954 jalview.io.PIRFile.useModellerOutput = modellerOutput.isSelected();
956 Cache.applicationProperties.setProperty("FIGURE_AUTOIDWIDTH",
957 Boolean.toString(autoIdWidth.isSelected()));
958 userIdWidth_actionPerformed();
959 Cache.applicationProperties.setProperty("FIGURE_FIXEDIDWIDTH",
960 userIdWidth.getText());
963 * Save Editing settings
965 Cache.applicationProperties.setProperty("AUTO_CALC_CONSENSUS",
966 Boolean.toString(autoCalculateConsCheck.isSelected()));
967 Cache.applicationProperties.setProperty("SORT_BY_TREE",
968 Boolean.toString(sortByTree.isSelected()));
969 Cache.applicationProperties.setProperty("PAD_GAPS",
970 Boolean.toString(padGaps.isSelected()));
972 if (!Platform.isJS())
974 wsPrefs.updateAndRefreshWsMenuConfig(false);
978 * Save Backups settings
980 Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
981 Boolean.toString(enableBackupFiles.isSelected()));
982 int preset = getComboIntStringKey(backupfilesPresetsCombo);
983 Cache.applicationProperties.setProperty(BackupFiles.NS + "_PRESET",
984 Integer.toString(preset));
986 if (preset == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
988 BackupFilesPresetEntry customBFPE = getBackupfilesCurrentEntry();
989 BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
990 BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM, customBFPE);
991 Cache.applicationProperties.setProperty(
992 BackupFilesPresetEntry.CUSTOMCONFIG, customBFPE.toString());
995 BackupFilesPresetEntry savedBFPE = BackupFilesPresetEntry.backupfilesPresetEntriesValues
997 Cache.applicationProperties.setProperty(
998 BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
1001 * Save Memory Settings
1003 Cache.applicationProperties.setProperty(
1004 MemorySetting.CUSTOMISED_SETTINGS,
1005 Boolean.toString(customiseMemorySetting.isSelected()));
1006 Cache.applicationProperties.setProperty(MemorySetting.MEMORY_JVMMEMPC,
1007 Integer.toString(jvmMemoryPercentSlider.getValue()));
1008 Cache.applicationProperties.setProperty(MemorySetting.MEMORY_JVMMEMMAX,
1009 jvmMemoryMaxTextField.getText());
1012 * save and close Preferences
1015 Cache.saveProperties();
1016 Desktop.instance.doConfigureStructurePrefs();
1019 frame.setClosed(true);
1020 } catch (Exception ex)
1025 public void saveProxySettings()
1027 String newProxyType = customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM
1028 : noProxy.isSelected() ? Cache.PROXYTYPE_NONE
1029 : Cache.PROXYTYPE_SYSTEM;
1030 Cache.applicationProperties.setProperty("USE_PROXY", newProxyType);
1031 Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText());
1032 Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText());
1033 Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText());
1034 Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText());
1035 Cache.setOrRemove("PROXY_AUTH",
1036 Boolean.toString(proxyAuth.isSelected()));
1037 Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText());
1038 Cache.proxyAuthPassword = proxyAuthPasswordPB.getPassword();
1039 Cache.setProxyPropertiesFromPreferences(previousProxyType);
1040 if (newProxyType.equals(Cache.PROXYTYPE_CUSTOM)
1041 || !newProxyType.equals(previousProxyType))
1043 // force a re-lookup of ws if proxytype is custom or has changed
1046 previousProxyType = newProxyType;
1050 * Do any necessary validation before saving settings. Return focus to the
1051 * first tab which fails validation.
1055 private boolean validateSettings()
1057 if (!validateStructure())
1059 structureTab.requestFocusInWindow();
1066 protected boolean validateStructure()
1068 return validateViewerPath();
1076 public void startupFileTextfield_mouseClicked()
1078 // TODO: JAL-3048 not needed for Jalview-JS
1079 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1080 JalviewFileChooser chooser = JalviewFileChooser
1081 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1082 chooser.setFileView(new JalviewFileView());
1083 chooser.setDialogTitle(
1084 MessageManager.getString("label.select_startup_file"));
1086 int value = chooser.showOpenDialog(this);
1088 if (value == JalviewFileChooser.APPROVE_OPTION)
1090 FileFormatI format = chooser.getSelectedFormat();
1093 Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
1096 startupFileTextfield
1097 .setText(chooser.getSelectedFile().getAbsolutePath());
1108 public void cancel_actionPerformed(ActionEvent e)
1112 if (!Platform.isJS())
1114 wsPrefs.updateWsMenuConfig(true);
1115 wsPrefs.refreshWs_actionPerformed(e);
1117 frame.setClosed(true);
1118 } catch (Exception ex)
1130 public void annotations_actionPerformed(ActionEvent e)
1132 conservation.setEnabled(annotations.isSelected());
1133 quality.setEnabled(annotations.isSelected());
1134 identity.setEnabled(annotations.isSelected());
1135 showOccupancy.setEnabled(annotations.isSelected());
1136 showGroupConsensus.setEnabled(annotations.isSelected());
1137 showGroupConservation.setEnabled(annotations.isSelected());
1138 showConsensHistogram.setEnabled(annotations.isSelected()
1139 && (identity.isSelected() || showGroupConsensus.isSelected()));
1140 showConsensLogo.setEnabled(annotations.isSelected()
1141 && (identity.isSelected() || showGroupConsensus.isSelected()));
1145 public void newLink_actionPerformed(ActionEvent e)
1147 GSequenceLink link = new GSequenceLink();
1148 boolean valid = false;
1151 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1152 MessageManager.getString("label.new_sequence_url_link"),
1153 JvOptionPane.OK_CANCEL_OPTION, -1,
1154 null) == JvOptionPane.OK_OPTION)
1156 if (link.checkValid())
1158 if (((UrlLinkTableModel) linkUrlTable.getModel())
1159 .isUniqueName(link.getName()))
1161 ((UrlLinkTableModel) linkUrlTable.getModel())
1162 .insertRow(link.getName(), link.getURL());
1167 link.notifyDuplicate();
1180 public void editLink_actionPerformed(ActionEvent e)
1182 GSequenceLink link = new GSequenceLink();
1184 int index = linkUrlTable.getSelectedRow();
1187 // button no longer enabled if row is not selected
1188 Console.debug("Edit with no row selected in linkUrlTable");
1192 int nameCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1194 int urlCol = ((UrlLinkTableModel) linkUrlTable.getModel())
1196 String oldName = linkUrlTable.getValueAt(index, nameCol).toString();
1197 link.setName(oldName);
1198 link.setURL(linkUrlTable.getValueAt(index, urlCol).toString());
1200 boolean valid = false;
1203 if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
1204 MessageManager.getString("label.edit_sequence_url_link"),
1205 JvOptionPane.OK_CANCEL_OPTION, -1,
1206 null) == JvOptionPane.OK_OPTION)
1208 if (link.checkValid())
1210 if ((oldName.equals(link.getName()))
1211 || (((UrlLinkTableModel) linkUrlTable.getModel())
1212 .isUniqueName(link.getName())))
1214 linkUrlTable.setValueAt(link.getName(), index, nameCol);
1215 linkUrlTable.setValueAt(link.getURL(), index, urlCol);
1220 link.notifyDuplicate();
1233 public void deleteLink_actionPerformed(ActionEvent e)
1235 int index = linkUrlTable.getSelectedRow();
1236 int modelIndex = -1;
1239 // button no longer enabled if row is not selected
1240 Console.debug("Delete with no row selected in linkUrlTable");
1245 modelIndex = linkUrlTable.convertRowIndexToModel(index);
1248 // make sure we use the model index to delete, and not the table index
1249 ((UrlLinkTableModel) linkUrlTable.getModel()).removeRow(modelIndex);
1256 * jalview.jbgui.GPreferences#showunconserved_actionPerformed(java.awt.event
1260 protected void showunconserved_actionPerformed(ActionEvent e)
1262 // TODO Auto-generated method stub
1263 super.showunconserved_actionPerformed(e);
1266 public static List<String> getGroupURLLinks()
1268 return groupURLLinks;
1272 public void minColour_actionPerformed(JPanel panel)
1274 JalviewColourChooser.showColourChooser(this,
1275 MessageManager.getString("label.select_colour_minimum_value"),
1280 public void maxColour_actionPerformed(JPanel panel)
1282 JalviewColourChooser.showColourChooser(this,
1283 MessageManager.getString("label.select_colour_maximum_value"),
1288 public void gapColour_actionPerformed(JPanel gap)
1290 if (!useLegacyGap.isSelected())
1292 JalviewColourChooser.showColourChooser(this,
1293 MessageManager.getString("label.select_gap_colour"), gap);
1298 public void hiddenColour_actionPerformed(JPanel hidden)
1300 JalviewColourChooser.showColourChooser(this,
1301 MessageManager.getString("label.select_hidden_colour"), hidden);
1305 protected void useLegacyGaps_actionPerformed(ActionEvent e)
1307 boolean enabled = useLegacyGap.isSelected();
1310 gapColour.setBackground(
1311 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
1315 gapColour.setBackground(
1316 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
1318 gapColour.setEnabled(!enabled);
1319 gapLabel.setEnabled(!enabled);
1323 protected void resetOvDefaults_actionPerformed(ActionEvent e)
1325 useLegacyGap.setSelected(false);
1326 useLegacyGaps_actionPerformed(null);
1327 showHiddenAtStart.setSelected(false);
1328 hiddenColour.setBackground(
1329 jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
1333 protected void userIdWidth_actionPerformed()
1337 String val = userIdWidth.getText().trim();
1338 if (val.length() > 0)
1340 Integer iw = Integer.parseInt(val);
1341 if (iw.intValue() < 12)
1343 throw new NumberFormatException();
1345 userIdWidth.setText(iw.toString());
1347 } catch (NumberFormatException x)
1349 userIdWidth.setText("");
1350 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1352 .getString("warn.user_defined_width_requirements"),
1353 MessageManager.getString("label.invalid_id_column_width"),
1354 JvOptionPane.WARNING_MESSAGE);
1359 protected void autoIdWidth_actionPerformed()
1361 userIdWidth.setEnabled(!autoIdWidth.isSelected());
1362 userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
1366 * Returns true if structure viewer path is to a valid executable, else shows
1367 * an error dialog. Does nothing if the path is empty, as is the case for Jmol
1368 * (built in to Jalview) or when Jalview is left to try default paths.
1370 private boolean validateViewerPath()
1372 if (structureViewerPath.getText().trim().length() > 0)
1374 File f = new File(structureViewerPath.getText());
1375 if (!f.canExecute())
1377 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1378 MessageManager.getString("label.invalid_viewer_path"),
1379 MessageManager.getString("label.invalid_viewer_path"),
1380 JvOptionPane.ERROR_MESSAGE);
1388 * If Chimera or ChimeraX or Pymol is selected, check it can be found on
1389 * default or user-specified path, if not show a warning/help dialog
1392 protected void structureViewer_actionPerformed(String selectedItem)
1394 if (selectedItem.equals(ViewerType.JMOL.name()))
1396 structureViewerPath.setEnabled(false);
1397 structureViewerPathLabel.setEnabled(false);
1400 boolean found = false;
1401 structureViewerPath.setEnabled(true);
1402 structureViewerPathLabel.setEnabled(true);
1403 structureViewerPathLabel.setText(MessageManager
1404 .formatMessage("label.viewer_path", selectedItem));
1407 * Try user-specified and standard paths for structure viewer executable
1409 String viewerPath = "";
1410 List<String> paths = null;
1413 ViewerType viewerType = ViewerType.valueOf(selectedItem);
1420 viewerPath = Cache.getDefault(CHIMERA_PATH, "");
1421 paths = StructureManager.getChimeraPaths(false);
1424 viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
1425 paths = StructureManager.getChimeraPaths(true);
1428 viewerPath = Cache.getDefault(PYMOL_PATH, "");
1429 paths = PymolManager.getPymolPaths();
1432 } catch (IllegalArgumentException e)
1434 // only valid entries should be in the drop-down
1436 structureViewerPath.setText(viewerPath);
1438 paths.add(0, structureViewerPath.getText());
1439 for (String path : paths)
1441 if (new File(path.trim()).canExecute())
1450 String[] options = { "OK", "Help" };
1451 int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
1452 JvSwingUtils.wrapTooltip(true,
1453 MessageManager.getString("label.viewer_missing")),
1454 "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
1455 null, options, options[0]);
1457 if (showHelp == JvOptionPane.NO_OPTION)
1459 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1462 Help.showHelpWindow(HelpId.StructureViewer);
1463 } catch (HelpSetException e)
1465 e.printStackTrace();
1468 else if (showHelp == JvOptionPane.OK_OPTION)
1470 this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
1471 CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
1474 for (int i = 0; i < 3; i++)
1476 structureViewerPath.setBackground(Color.PINK);
1478 structureViewerPath.setBackground(Color.WHITE);
1481 } catch (InterruptedException e)
1489 public class OptionsParam
1491 private String name;
1493 private String code;
1495 public OptionsParam(String name, String code)
1501 public String getName()
1506 public void setName(String name)
1511 public String getCode()
1516 public void setCode(String code)
1522 public String toString()
1528 public boolean equals(Object that)
1530 if (!(that instanceof OptionsParam))
1534 return this.code.equalsIgnoreCase(((OptionsParam) that).code);
1538 public int hashCode()
1540 return name.hashCode() + code.hashCode();
1544 private class UrlListSelectionHandler implements ListSelectionListener
1548 public void valueChanged(ListSelectionEvent e)
1550 ListSelectionModel lsm = (ListSelectionModel) e.getSource();
1552 int index = lsm.getMinSelectionIndex();
1555 // no selection, so disable delete/edit buttons
1556 editLink.setEnabled(false);
1557 deleteLink.setEnabled(false);
1560 int modelIndex = linkUrlTable.convertRowIndexToModel(index);
1562 // enable/disable edit and delete link buttons
1563 if (((UrlLinkTableModel) linkUrlTable.getModel())
1564 .isRowDeletable(modelIndex))
1566 deleteLink.setEnabled(true);
1570 deleteLink.setEnabled(false);
1573 if (((UrlLinkTableModel) linkUrlTable.getModel())
1574 .isRowEditable(modelIndex))
1576 editLink.setEnabled(true);
1580 editLink.setEnabled(false);