diff --git a/code/src/java/pcgen/gui2/dialog/LanguageChooserDialog.java b/code/src/java/pcgen/gui2/dialog/LanguageChooserDialog.java index 4de9b4ec612..4b3cce4d288 100644 --- a/code/src/java/pcgen/gui2/dialog/LanguageChooserDialog.java +++ b/code/src/java/pcgen/gui2/dialog/LanguageChooserDialog.java @@ -1,20 +1,20 @@ /* * Copyright 2010 Connor Petty - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * */ package pcgen.gui2.dialog; @@ -30,7 +30,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import javax.swing.JDialog; import javax.swing.JLabel; @@ -38,6 +37,7 @@ import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import pcgen.core.Language; @@ -115,7 +115,6 @@ public void windowClosed(WindowEvent e) JSplitPane split = new JSplitPane(); JPanel leftPane = new JPanel(new BorderLayout()); - //leftPane.add(new JLabel("Available Languages"), BorderLayout.NORTH); availTable.setAutoCreateRowSorter(true); availTable.setTreeViewModel(treeViewModel); availTable.getRowSorter().toggleSortOrder(0); @@ -172,8 +171,8 @@ private void doAdd(final javafx.event.ActionEvent actionEvent) if (!data.isEmpty()) { data.stream() - .filter(object -> object instanceof Language) - .map(object -> (Language) object) + .filter(Language.class::isInstance) + .map(Language.class::cast) .forEach(chooser::addSelected); } } @@ -189,14 +188,19 @@ private void doRemove(final javafx.event.ActionEvent actionEvent) private void doOK(final javafx.event.ActionEvent actionEvent) { - chooser.commit(); - dispose(); + // FX thread → EDT: commit() and dispose() must run on the EDT (#6517). + SwingUtilities.invokeLater(() -> { + chooser.commit(); + dispose(); + }); } private void doRollback(final javafx.event.ActionEvent actionEvent) { - chooser.rollback(); - dispose(); + SwingUtilities.invokeLater(() -> { + chooser.rollback(); + dispose(); + }); } @@ -255,6 +259,7 @@ public Object getData(Language element, int column) @Override public void setData(Object value, Language element, int column) { + // no-op: this view is read-only } @Override @@ -266,7 +271,7 @@ public List getDataColumns() @Override public String getPrefsKey() { - return LanguageBundle.getString("in_sumLangAvailable"); //$NON-NLS-1$; + return LanguageBundle.getString("in_sumLangAvailable"); //$NON-NLS-1$ } } @@ -299,7 +304,7 @@ public List> getPaths(Language pobj) .stream() .map(pcgen.cdom.enumeration.Type::toString) .map(type -> new TreeViewPath<>(pobj, type)) - .collect(Collectors.toUnmodifiableList()); + .toList(); default -> throw new InternalError(); }; } diff --git a/code/src/java/pcgen/gui2/tabs/summary/LanguageTableModel.java b/code/src/java/pcgen/gui2/tabs/summary/LanguageTableModel.java index c8ed8e4d4a8..00ca2f594b0 100644 --- a/code/src/java/pcgen/gui2/tabs/summary/LanguageTableModel.java +++ b/code/src/java/pcgen/gui2/tabs/summary/LanguageTableModel.java @@ -21,6 +21,7 @@ import java.awt.CardLayout; import java.awt.Component; import java.awt.Frame; +import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -29,6 +30,7 @@ import javax.swing.AbstractCellEditor; import javax.swing.Box; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -46,6 +48,7 @@ import pcgen.gui2.UIPropertyContext; import pcgen.gui2.dialog.LanguageChooserDialog; import pcgen.gui2.tabs.Utilities; +import pcgen.gui2.tabs.models.DeferredCharacterComboBoxModel; import pcgen.gui2.util.SignIcon.Sign; import pcgen.gui2.util.table.TableCellUtilities; import pcgen.gui3.utilty.ColorUtilty; @@ -256,8 +259,13 @@ public void actionPerformed(ActionEvent e) { if (ADD_ID.equals(e.getActionCommand())) { + // Resolve the chooser BEFORE the flush: committing may mutate + // the languages list and invalidate getEditingRow() (#6517). + LanguageChooserFacade chooser = choosers.getElementAt( + table.getEditingRow() - languages.getSize()); + flushPendingDeferredComboBoxCommit(); + Frame frame = JOptionPane.getFrameForComponent(table); - LanguageChooserFacade chooser = choosers.getElementAt(table.getEditingRow() - languages.getSize()); LanguageChooserDialog dialog = new LanguageChooserDialog(frame, chooser); dialog.setLocationRelativeTo(frame); dialog.setVisible(true); @@ -270,6 +278,18 @@ public void actionPerformed(ActionEvent e) cancelCellEditing(); } + /** Commit any pending DeferredCharacterComboBoxModel value on the focused combo. */ + private void flushPendingDeferredComboBoxCommit() + { + Component focused = KeyboardFocusManager + .getCurrentKeyboardFocusManager().getFocusOwner(); + if (focused instanceof JComboBox combo + && combo.getModel() instanceof DeferredCharacterComboBoxModel model) + { + model.commitSelectedItem(model.getSelectedItem()); + } + } + @Override public Object getCellEditorValue() { @@ -284,7 +304,6 @@ private class Renderer extends JPanel implements TableCellRenderer private static final String ADD_ID = "Add"; private static final String REMOVE_ID = "Remove"; private CardLayout cardLayout = new CardLayout(); - //private JPanel cellPanel = new JPanel(); private JLabel cellLabel = new JLabel(); private JButton addButton = Utilities.createSignButton(Sign.Plus); private JButton removeButton = Utilities.createSignButton(Sign.Minus); @@ -317,8 +336,8 @@ public Component getTableCellRendererComponent(JTable jTable, Object value, bool TableCellUtilities.setToRowBackground(this, jTable, row); if (row < languages.getSize()) { - boolean automatic = value instanceof Language && character.isAutomatic((Language) value); - boolean removable = value instanceof Language && character.isRemovable((Language) value); + boolean automatic = value instanceof Language language && character.isAutomatic(language); + boolean removable = value instanceof Language language && character.isRemovable(language); if (automatic) { cellLabel.setForeground(ColorUtilty.colorToAWTColor(UIPropertyContext.getAutomaticColor()));