package jalview.ws2.gui;
import static java.lang.String.format;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletionStage;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.ToolTipManager;
import jalview.datamodel.AlignmentView;
import jalview.gui.AlignFrame;
import jalview.gui.AlignViewport;
import jalview.gui.JvSwingUtils;
import jalview.gui.WebserviceInfo;
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.PollingTaskExecutor;
import jalview.ws2.operations.AlignmentOperation;
import jalview.ws2.operations.AlignmentWorker;
public class AlignmentMenuBuilder implements MenuEntryProviderI
{
AlignmentOperation operation;
public AlignmentMenuBuilder(AlignmentOperation operation)
{
this.operation = operation;
}
public void buildMenu(JMenu parent, AlignFrame frame)
{
if (operation.canSubmitGaps())
{
var alignSubmenu = new JMenu(operation.getName());
buildMenu(alignSubmenu, frame, false);
parent.add(alignSubmenu);
var realignSubmenu = new JMenu(MessageManager.formatMessage(
"label.realign_with_params", operation.getName()));
realignSubmenu.setToolTipText(MessageManager
.getString("label.align_sequences_to_existing_alignment"));
buildMenu(realignSubmenu, frame, true);
parent.add(realignSubmenu);
}
else
{
buildMenu(parent, frame, false);
}
}
protected void buildMenu(JMenu parent, AlignFrame frame,
boolean submitGaps)
{
final String action = submitGaps ? "Align" : "Realign";
final var calcName = operation.getName();
{
var item = new JMenuItem(MessageManager.formatMessage(
"label.calcname_with_default_settings", calcName));
item.setToolTipText(MessageManager
.formatMessage("label.action_with_default_settings", action));
item.addActionListener((event) -> {
final AlignmentView msa = frame.gatherSequencesForAlignment();
if (msa != null)
{
startWorker(frame, msa, Collections.emptyList(), submitGaps);
}
});
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_alignment"));
item.addActionListener((event) -> {
AlignmentView msa = frame.gatherSequencesForAlignment();
if (msa != null)
{
openEditParamsDialog(operation.getParamStore(), null, null)
.thenAcceptAsync((arguments) -> {
if (arguments != null)
{
startWorker(frame, msa, arguments, submitGaps);
}
});
}
});
parent.add(item);
}
var presets = operation.getParamStore().getPresets();
if (presets != null && presets.size() > 0)
{
final var presetList = new JMenu(MessageManager
.formatMessage("label.run_with_preset_params", calcName));
final var showToolTipFor = ToolTipManager.sharedInstance()
.getDismissDelay();
for (final var preset : presets)
{
var item = new JMenuItem(preset.getName());
final int QUICK_TOOLTIP = 1500;
item.addMouseListener(new MouseAdapter()
{
@Override
public void mouseEntered(MouseEvent e)
{
ToolTipManager.sharedInstance().setDismissDelay(QUICK_TOOLTIP);
}
@Override
public void mouseExited(MouseEvent e)
{
ToolTipManager.sharedInstance().setDismissDelay(showToolTipFor);
}
});
String tooltip = JvSwingUtils.wrapTooltip(true,
format("%s
%s",
MessageManager.getString(
preset.isModifiable() ? "label.user_preset"
: "label.service_preset"),
preset.getDescription()));
item.setToolTipText(tooltip);
item.addActionListener((event) -> {
AlignmentView msa = frame.gatherSequencesForAlignment();
startWorker(frame, msa, preset.getArguments(), submitGaps);
});
presetList.add(item);
}
parent.add(presetList);
}
}
private CompletionStage> openEditParamsDialog(
ParamDatastoreI paramStore, WsParamSetI preset,
List 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 void startWorker(AlignFrame frame, AlignmentView msa,
List arguments, boolean submitGaps)
{
AlignViewport viewport = frame.getViewport();
PollingTaskExecutor executor = frame.getViewport().getWSExecutor();
if (msa != null)
{
String panelInfo = String.format("%s using service hosted at %s%n%s",
operation.getName(), operation.getHostName(),
Objects.requireNonNullElse(operation.getDescription(), ""));
var wsInfo = new WebserviceInfo(operation.getName(), panelInfo, false);
final String alnTitle = frame.getTitle();
AlignmentWorker worker = new AlignmentWorker(operation, msa,
arguments, submitGaps, true, viewport);
String outputHeader = String.format("%s of %s%nJob details%n",
submitGaps ? "Re-alignment" : "Alignment", alnTitle);
var awl = new AlignmentProgressUpdater(worker, wsInfo, frame,
outputHeader);
worker.setResultConsumer(awl);
worker.addListener(awl);
executor.submit(worker);
}
}
}