ExperimentDocumentSwingActions.java
package org.hammer;
import java.awt.Cursor;
import java.nio.file.Path;
import java.util.Objects;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import org.hammer.audio.experiment.document.ExperimentDocumentPreview;
import org.hammer.audio.experiment.document.ExperimentDocumentService;
/** Installs safe, non-mutating portable experiment-document actions into the Swing workbench. */
final class ExperimentDocumentSwingActions {
private static final String FILE_MENU = "File";
private static final String DIALOG_TITLE = "Portable experiment document";
private final JFrame owner;
private final ExperimentDocumentService documentService;
ExperimentDocumentSwingActions(JFrame owner, ExperimentDocumentService documentService) {
this.owner = Objects.requireNonNull(owner, "owner");
this.documentService = Objects.requireNonNull(documentService, "documentService");
}
/** Add one keyboard-accessible inspect/normalize action to the existing File menu. */
void install() {
JMenu fileMenu = findMenu(owner.getJMenuBar(), FILE_MENU);
if (fileMenu == null) {
throw new IllegalStateException("Desktop File menu is unavailable");
}
JMenuItem inspect = new JMenuItem("Inspect experiment document...");
inspect.setToolTipText(
"Validate and preview a .audioexp setup without applying or executing it.");
inspect.addActionListener(event -> chooseDocument());
fileMenu.insert(inspect, Math.min(fileMenu.getItemCount(), 1));
}
/** Validate and preview one explicitly selected document without applying or executing it. */
void inspect(Path source) {
Objects.requireNonNull(source, "source");
owner.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new SwingWorker<ExperimentDocumentPreview, Void>() {
@Override
protected ExperimentDocumentPreview doInBackground() throws Exception {
return documentService.preview(source);
}
@Override
protected void done() {
owner.setCursor(Cursor.getDefaultCursor());
try {
new ExperimentDocumentPreviewDialog(owner, documentService).show(source, get());
} catch (InterruptedException exception) {
Thread.currentThread().interrupt();
showFailure("Preview was interrupted.", exception);
} catch (java.util.concurrent.ExecutionException exception) {
showFailure("Experiment document preview failed.", exception.getCause());
}
}
}.execute();
}
private void chooseDocument() {
Path source = ExperimentDocumentFileChooser.chooseOpen(owner);
if (source != null) {
inspect(source);
}
}
private static JMenu findMenu(JMenuBar menuBar, String title) {
if (menuBar == null) {
return null;
}
for (int index = 0; index < menuBar.getMenuCount(); index++) {
JMenu menu = menuBar.getMenu(index);
if (menu != null && title.equals(menu.getText())) {
return menu;
}
}
return null;
}
private void showFailure(String message, Throwable failure) {
String detail = failure == null || failure.getMessage() == null ? "" : failure.getMessage();
JOptionPane.showMessageDialog(
owner,
detail.isBlank() ? message : message + "\n" + detail,
DIALOG_TITLE,
JOptionPane.ERROR_MESSAGE);
}
}