JAL-3878 Separate gui elements from operations.
[jalview.git] / src / jalview / ws2 / gui / AnnotationMenuBuilder.java
1 package jalview.ws2.gui;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6 import java.util.concurrent.CompletionStage;
7
8 import javax.swing.JCheckBoxMenuItem;
9 import javax.swing.JMenu;
10 import javax.swing.JMenuItem;
11 import javax.swing.event.MenuEvent;
12 import javax.swing.event.MenuListener;
13
14 import jalview.api.AlignCalcManagerI2;
15 import jalview.api.AlignmentViewPanel;
16 import jalview.gui.AlignFrame;
17 import jalview.gui.AlignViewport;
18 import jalview.gui.WsJobParameters;
19 import jalview.util.MessageManager;
20 import jalview.ws.params.ArgumentI;
21 import jalview.ws.params.ParamDatastoreI;
22 import jalview.ws.params.WsParamSetI;
23 import jalview.ws2.MenuEntryProviderI;
24 import jalview.ws2.PollingTaskExecutor;
25 import jalview.ws2.operations.AnnotationOperation;
26 import jalview.ws2.operations.AnnotationServiceWorker;
27
28 public class AnnotationMenuBuilder implements MenuEntryProviderI
29 {
30   final AnnotationOperation operation;
31   
32   public AnnotationMenuBuilder(AnnotationOperation operation)
33   {
34     this.operation = operation;
35   }
36
37   @Override
38   public void buildMenu(JMenu parent, AlignFrame frame)
39   {
40     if (operation.isInteractive())
41       buildInteractiveMenu(parent, frame);
42     else
43       buildClassicMenu(parent, frame);
44   }
45
46   protected void buildClassicMenu(JMenu parent, AlignFrame frame)
47   {
48     final var calcName = operation.getName();
49     PollingTaskExecutor wsExecutor = frame.getViewport().getWSExecutor();
50     final var calcManager = frame.getViewport().getCalcManager();
51     {
52       var item = new JMenuItem(MessageManager.formatMessage(
53           "label.calcname_with_default_settings", calcName));
54       item.addActionListener((event) -> {
55         var worker = createWorker(Collections.emptyList(), frame, calcManager);
56         calcManager.startWorker(worker);
57       });
58       parent.add(item);
59     }
60     if (operation.hasParameters())
61     {
62       var item = new JMenuItem(
63           MessageManager.getString("label.edit_settings_and_run"));
64       item.setToolTipText(MessageManager.getString(
65           "label.view_and_change_parameters_before_running_calculation"));
66       item.addActionListener((event) -> {
67         openEditParamsDialog(operation.getParamStore(), null, null)
68             .thenAcceptAsync((arguments) -> {
69               if (arguments != null)
70               {
71                 var worker = createWorker(arguments, frame, calcManager);
72                 calcManager.startWorker(worker);
73               }
74             });
75       });
76       parent.add(item);
77     }
78   }
79
80   protected void buildInteractiveMenu(JMenu parent, AlignFrame frame)
81   {
82     final var calcName = operation.getName();
83     final var calcManager = frame.getViewport().getCalcManager();
84     final var arguments = new ArrayList<ArgumentI>();
85     final JCheckBoxMenuItem runItem;
86     {
87       // TODO use MessageManager and set tool tip text
88       runItem = new JCheckBoxMenuItem(
89           String.format("%s calculations", calcName));
90       runItem.addActionListener((event) -> {
91         calcManager.removeWorkersForName(calcName);
92         var worker = createWorker(arguments, frame, calcManager);
93         calcManager.registerWorker(worker);
94       });
95       parent.add(runItem);
96     }
97     JMenuItem _editItem = null;
98     if (operation.hasParameters())
99     {
100       // TODO use MessageManager and set tool tip text
101       _editItem = new JMenuItem(
102           String.format("Edit %s settings", calcName));
103       _editItem.addActionListener((event) -> {
104         openEditParamsDialog(operation.getParamStore(), null, null)
105             .thenAcceptAsync((args) -> {
106               if (arguments != null)
107               {
108                 arguments.clear();
109                 arguments.addAll(args);
110                 calcManager.removeWorkersForName(calcName);
111                 var worker = createWorker(arguments, frame, calcManager);
112                 calcManager.registerWorker(worker);
113               }
114             });
115       });
116       parent.add(_editItem);
117     }
118     final var editItem = _editItem;
119
120     parent.addMenuListener(new MenuListener()
121       {
122         @Override
123         public void menuSelected(MenuEvent e)
124         {
125           var isNuc = frame.getViewport().getAlignment().isNucleotide();
126           var menuEnabled = (isNuc && operation.isNucleotideOperation()) ||
127               (!isNuc && operation.isProteinOperation());
128           runItem.setEnabled(menuEnabled);
129           if (editItem != null)
130             editItem.setEnabled(menuEnabled);
131           boolean currentlyRunning = calcManager.getWorkersForName(calcName).size() > 0;
132           runItem.setSelected(currentlyRunning);
133         }
134
135         @Override
136         public void menuDeselected(MenuEvent e) {}
137
138         @Override
139         public void menuCanceled(MenuEvent e) {}
140       });
141   }
142   
143
144   private CompletionStage<List<ArgumentI>> openEditParamsDialog(
145           ParamDatastoreI paramStore, WsParamSetI preset,
146           List<ArgumentI> arguments)
147   {
148     WsJobParameters jobParams;
149     if (preset == null && arguments != null && arguments.size() > 0)
150       jobParams = new WsJobParameters(paramStore, preset, arguments);
151     else
152       jobParams = new WsJobParameters(paramStore, preset, null);
153     if (preset != null)
154     {
155       jobParams.setName(MessageManager.getString(
156           "label.adjusting_parameters_for_calculation"));
157     }
158     var stage = jobParams.showRunDialog();
159     return stage.thenApply((startJob) -> {
160       if (startJob)
161       {
162         if (jobParams.getPreset() == null)
163         {
164           return jobParams.getJobParams();
165         }
166         else
167         {
168           return jobParams.getPreset().getArguments();
169         }
170       }
171       else
172       {
173         return null;
174       }
175     });
176   }
177   
178
179   private AnnotationServiceWorker createWorker(
180       List<ArgumentI> arguments, AlignFrame frame, AlignCalcManagerI2 calcManager)
181   {
182     /* What is the purpose of AlignViewport and AlignmentViewPanel? */
183     AlignViewport viewport = frame.getCurrentView();
184     AlignmentViewPanel alignPanel = frame.alignPanel;
185     return new AnnotationServiceWorker(operation,
186         arguments, viewport, alignPanel, frame, frame,
187         calcManager);
188   }
189
190 }