+ protected JComboBox<String> buildModelOptionsList()
+ {
+ JComboBox<String> scoreModelsCombo = new JComboBox<>();
+ if (renderer == null)
+ {
+ renderer = new ComboBoxTooltipRenderer();
+ }
+ scoreModelsCombo.setRenderer(renderer);
+
+ /*
+ * show tooltip on mouse over the combobox
+ * note the listener has to be on the components that make up
+ * the combobox, doesn't work if just on the combobox
+ */
+ final MouseAdapter mouseListener = new MouseAdapter()
+ {
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ scoreModelsCombo.setToolTipText(
+ tips.get(scoreModelsCombo.getSelectedIndex()));
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e)
+ {
+ scoreModelsCombo.setToolTipText(null);
+ }
+ };
+ for (Component c : scoreModelsCombo.getComponents())
+ {
+ c.addMouseListener(mouseListener);
+ }
+
+ updateScoreModels(scoreModelsCombo, tips);
+
+ /*
+ * set the list of tooltips on the combobox's renderer
+ */
+ renderer.setTooltips(tips);
+
+ return scoreModelsCombo;
+ }
+
+ private void updateScoreModels(JComboBox<String> comboBox,
+ List<String> toolTips)
+ {
+ Object curSel = comboBox.getSelectedItem();
+ toolTips.clear();
+ DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
+
+ /*
+ * select the score models applicable to the alignment type
+ */
+ boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
+ List<ScoreModelI> models = getApplicableScoreModels(nucleotide,
+ pca.isSelected());
+
+ /*
+ * now we can actually add entries to the combobox,
+ * remembering their descriptions for tooltips
+ */
+ boolean selectedIsPresent = false;
+ for (ScoreModelI sm : models)
+ {
+ if (curSel != null && sm.getName().equals(curSel))
+ {
+ selectedIsPresent = true;
+ curSel = sm.getName();
+ }
+ model.addElement(sm.getName());
+
+ /*
+ * tooltip is description if provided, else text lookup with
+ * fallback on the model name
+ */
+ String tooltip = sm.getDescription();
+ if (tooltip == null)
+ {
+ tooltip = MessageManager.getStringOrReturn("label.score_model_",
+ sm.getName());
+ }
+ toolTips.add(tooltip);
+ }
+
+ if (selectedIsPresent)
+ {
+ model.setSelectedItem(curSel);
+ }
+ // finally, update the model
+ comboBox.setModel(model);
+ }
+
+ /**
+ * Builds a list of score models which are applicable for the alignment and
+ * calculation type (peptide or generic models for protein, nucleotide or
+ * generic models for nucleotide).
+ * <p>
+ * As a special case, includes BLOSUM62 as an extra option for nucleotide PCA.
+ * This is for backwards compatibility with Jalview prior to 2.8 when BLOSUM62
+ * was the only score matrix supported. This is included if property
+ * BLOSUM62_PCA_FOR_NUCLEOTIDE is set to true in the Jalview properties file.
+ *
+ * @param nucleotide
+ * @param forPca
+ * @return
+ */
+ protected static List<ScoreModelI> getApplicableScoreModels(
+ boolean nucleotide, boolean forPca)
+ {
+ List<ScoreModelI> filtered = new ArrayList<>();
+
+ ScoreModels scoreModels = ScoreModels.getInstance();
+ for (ScoreModelI sm : scoreModels.getModels())
+ {
+ if (!nucleotide && sm.isProtein() || nucleotide && sm.isDNA())
+ {
+ filtered.add(sm);
+ }
+ }
+
+ /*
+ * special case: add BLOSUM62 as last option for nucleotide PCA,
+ * for backwards compatibility with Jalview < 2.8 (JAL-2962)
+ */
+ if (nucleotide && forPca
+ && Cache.getDefault(Preferences.BLOSUM62_PCA_FOR_NUCLEOTIDE,
+ false))
+ {
+ filtered.add(scoreModels.getBlosum62());
+ }
+
+ return filtered;
+ }
+
+ /**
+ * Open and calculate the selected tree or PCA on 'OK'
+ */
+ protected void calculate_actionPerformed()