|
37 | 37 | import java.awt.event.WindowAdapter; |
38 | 38 | import java.awt.event.WindowEvent; |
39 | 39 | import java.io.File; |
| 40 | +import java.lang.reflect.InvocationTargetException; |
40 | 41 |
|
41 | 42 | import javax.swing.JFileChooser; |
42 | 43 | import javax.swing.JMenu; |
|
48 | 49 | import org.scijava.app.AppService; |
49 | 50 | import org.scijava.display.Display; |
50 | 51 | import org.scijava.event.EventService; |
| 52 | +import org.scijava.log.LogService; |
51 | 53 | import org.scijava.menu.MenuService; |
52 | 54 | import org.scijava.menu.ShadowMenu; |
53 | 55 | import org.scijava.platform.event.AppMenusCreatedEvent; |
54 | 56 | import org.scijava.plugin.Parameter; |
| 57 | +import org.scijava.thread.ThreadService; |
55 | 58 | import org.scijava.ui.AbstractUserInterface; |
56 | 59 | import org.scijava.ui.SystemClipboard; |
57 | 60 | import org.scijava.ui.UIService; |
@@ -90,6 +93,12 @@ public abstract class AbstractSwingUI extends AbstractUserInterface implements |
90 | 93 | @Parameter |
91 | 94 | private UIService uiService; |
92 | 95 |
|
| 96 | + @Parameter |
| 97 | + private ThreadService threadService; |
| 98 | + |
| 99 | + @Parameter |
| 100 | + private LogService log; |
| 101 | + |
93 | 102 | private SwingApplicationFrame appFrame; |
94 | 103 | private SwingToolBar toolBar; |
95 | 104 | private SwingStatusBar statusBar; |
@@ -125,19 +134,31 @@ public SystemClipboard getSystemClipboard() { |
125 | 134 |
|
126 | 135 | @Override |
127 | 136 | public File chooseFile(final File file, final String style) { |
128 | | - final JFileChooser chooser = new JFileChooser(file); |
129 | | - if (FileWidget.DIRECTORY_STYLE.equals(style)) { |
130 | | - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); |
131 | | - } |
132 | | - final int rval; |
133 | | - if (FileWidget.SAVE_STYLE.equals(style)) { |
134 | | - rval = chooser.showSaveDialog(appFrame); |
| 137 | + final File[] result = new File[1]; |
| 138 | + try { |
| 139 | + // NB: We show the JFileChooser on the EDT because otherwise there could |
| 140 | + // be a deadlock, particularly on macOS. See scijava/scijava-ui-swing#28. |
| 141 | + threadService.invoke(() -> { |
| 142 | + final JFileChooser chooser = new JFileChooser(file); |
| 143 | + if (FileWidget.DIRECTORY_STYLE.equals(style)) { |
| 144 | + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); |
| 145 | + } |
| 146 | + final int rval; |
| 147 | + if (FileWidget.SAVE_STYLE.equals(style)) { |
| 148 | + rval = chooser.showSaveDialog(appFrame); |
| 149 | + } |
| 150 | + else { // default behavior |
| 151 | + rval = chooser.showOpenDialog(appFrame); |
| 152 | + } |
| 153 | + if (rval == JFileChooser.APPROVE_OPTION) { |
| 154 | + result[0] = chooser.getSelectedFile(); |
| 155 | + } |
| 156 | + }); |
135 | 157 | } |
136 | | - else { // default behavior |
137 | | - rval = chooser.showOpenDialog(appFrame); |
| 158 | + catch (final InvocationTargetException | InterruptedException exc) { |
| 159 | + log.error(exc); |
138 | 160 | } |
139 | | - if (rval != JFileChooser.APPROVE_OPTION) return null; |
140 | | - return chooser.getSelectedFile(); |
| 161 | + return result[0]; |
141 | 162 | } |
142 | 163 |
|
143 | 164 | @Override |
|
0 commit comments