--- /dev/null
+package jalview.ws2.gui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
+
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignmentViewPanel;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.gui.WsJobParameters;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.WsParamSetI;
+import jalview.ws2.MenuEntryProviderI;
+import jalview.ws2.PollingTaskExecutor;
+import jalview.ws2.operations.AnnotationOperation;
+import jalview.ws2.operations.AnnotationServiceWorker;
+
+public class AnnotationMenuBuilder implements MenuEntryProviderI
+{
+ final AnnotationOperation operation;
+
+ public AnnotationMenuBuilder(AnnotationOperation operation)
+ {
+ this.operation = operation;
+ }
+
+ @Override
+ public void buildMenu(JMenu parent, AlignFrame frame)
+ {
+ if (operation.isInteractive())
+ buildInteractiveMenu(parent, frame);
+ else
+ buildClassicMenu(parent, frame);
+ }
+
+ protected void buildClassicMenu(JMenu parent, AlignFrame frame)
+ {
+ final var calcName = operation.getName();
+ PollingTaskExecutor wsExecutor = frame.getViewport().getWSExecutor();
+ final var calcManager = frame.getViewport().getCalcManager();
+ {
+ var item = new JMenuItem(MessageManager.formatMessage(
+ "label.calcname_with_default_settings", calcName));
+ item.addActionListener((event) -> {
+ var worker = createWorker(Collections.emptyList(), frame, calcManager);
+ calcManager.startWorker(worker);
+ });
+ parent.add(item);
+ }
+ if (operation.hasParameters())
+ {
+ var item = new JMenuItem(
+ MessageManager.getString("label.edit_settings_and_run"));
+ item.setToolTipText(MessageManager.getString(
+ "label.view_and_change_parameters_before_running_calculation"));
+ item.addActionListener((event) -> {
+ openEditParamsDialog(operation.getParamStore(), null, null)
+ .thenAcceptAsync((arguments) -> {
+ if (arguments != null)
+ {
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.startWorker(worker);
+ }
+ });
+ });
+ parent.add(item);
+ }
+ }
+
+ protected void buildInteractiveMenu(JMenu parent, AlignFrame frame)
+ {
+ final var calcName = operation.getName();
+ final var calcManager = frame.getViewport().getCalcManager();
+ final var arguments = new ArrayList<ArgumentI>();
+ final JCheckBoxMenuItem runItem;
+ {
+ // TODO use MessageManager and set tool tip text
+ runItem = new JCheckBoxMenuItem(
+ String.format("%s calculations", calcName));
+ runItem.addActionListener((event) -> {
+ calcManager.removeWorkersForName(calcName);
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.registerWorker(worker);
+ });
+ parent.add(runItem);
+ }
+ JMenuItem _editItem = null;
+ if (operation.hasParameters())
+ {
+ // TODO use MessageManager and set tool tip text
+ _editItem = new JMenuItem(
+ String.format("Edit %s settings", calcName));
+ _editItem.addActionListener((event) -> {
+ openEditParamsDialog(operation.getParamStore(), null, null)
+ .thenAcceptAsync((args) -> {
+ if (arguments != null)
+ {
+ arguments.clear();
+ arguments.addAll(args);
+ calcManager.removeWorkersForName(calcName);
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.registerWorker(worker);
+ }
+ });
+ });
+ parent.add(_editItem);
+ }
+ final var editItem = _editItem;
+
+ parent.addMenuListener(new MenuListener()
+ {
+ @Override
+ public void menuSelected(MenuEvent e)
+ {
+ var isNuc = frame.getViewport().getAlignment().isNucleotide();
+ var menuEnabled = (isNuc && operation.isNucleotideOperation()) ||
+ (!isNuc && operation.isProteinOperation());
+ runItem.setEnabled(menuEnabled);
+ if (editItem != null)
+ editItem.setEnabled(menuEnabled);
+ boolean currentlyRunning = calcManager.getWorkersForName(calcName).size() > 0;
+ runItem.setSelected(currentlyRunning);
+ }
+
+ @Override
+ public void menuDeselected(MenuEvent e) {}
+
+ @Override
+ public void menuCanceled(MenuEvent e) {}
+ });
+ }
+
+
+ private CompletionStage<List<ArgumentI>> openEditParamsDialog(
+ ParamDatastoreI paramStore, WsParamSetI preset,
+ List<ArgumentI> arguments)
+ {
+ WsJobParameters jobParams;
+ if (preset == null && arguments != null && arguments.size() > 0)
+ jobParams = new WsJobParameters(paramStore, preset, arguments);
+ else
+ jobParams = new WsJobParameters(paramStore, preset, null);
+ if (preset != null)
+ {
+ jobParams.setName(MessageManager.getString(
+ "label.adjusting_parameters_for_calculation"));
+ }
+ var stage = jobParams.showRunDialog();
+ return stage.thenApply((startJob) -> {
+ if (startJob)
+ {
+ if (jobParams.getPreset() == null)
+ {
+ return jobParams.getJobParams();
+ }
+ else
+ {
+ return jobParams.getPreset().getArguments();
+ }
+ }
+ else
+ {
+ return null;
+ }
+ });
+ }
+
+
+ private AnnotationServiceWorker createWorker(
+ List<ArgumentI> arguments, AlignFrame frame, AlignCalcManagerI2 calcManager)
+ {
+ /* What is the purpose of AlignViewport and AlignmentViewPanel? */
+ AlignViewport viewport = frame.getCurrentView();
+ AlignmentViewPanel alignPanel = frame.alignPanel;
+ return new AnnotationServiceWorker(operation,
+ arguments, viewport, alignPanel, frame, frame,
+ calcManager);
+ }
+
+}